├── string.h ├── test ├── generate_files_vs2015.bat ├── generate_files_vs2017.bat ├── generate_files_vs2019.bat ├── ch_test.h ├── premake5.lua └── ch_test.cpp ├── .gitattributes ├── thirdparty ├── premake5.exe └── wglext.h ├── .gitignore ├── opengl.cpp ├── readme.md ├── time.cpp ├── pool_allocator.h ├── hash.h ├── win32 ├── memory_win32.cpp ├── filesystem_win32.h ├── opengl_win32.h ├── os_win32.h ├── time_win32.cpp ├── os_win32.cpp ├── opengl_win32.cpp ├── window_win32.cpp └── filesystem_win32.cpp ├── premake5.lua ├── templates.h ├── os.h ├── memory.h ├── allocator.h ├── types.h ├── window.h ├── allocator.cpp ├── time.h ├── pool_allocator.cpp ├── gap_buffer.h ├── input.h ├── memory.cpp ├── hash_table.h ├── filesystem.h ├── string.cpp ├── core.h ├── array.h ├── filesystem.cpp ├── math.cpp ├── opengl.h └── math.h /string.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colbyhall/ch_stl/HEAD/string.h -------------------------------------------------------------------------------- /test/generate_files_vs2015.bat: -------------------------------------------------------------------------------- 1 | call ..\thirdparty\premake5.exe vs2015 -------------------------------------------------------------------------------- /test/generate_files_vs2017.bat: -------------------------------------------------------------------------------- 1 | call ..\thirdparty\premake5.exe vs2017 -------------------------------------------------------------------------------- /test/generate_files_vs2019.bat: -------------------------------------------------------------------------------- 1 | call ..\thirdparty\premake5.exe vs2019 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.cpp linguist-language=C++ 2 | *.h linguist-language=C++ -------------------------------------------------------------------------------- /thirdparty/premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colbyhall/ch_stl/HEAD/thirdparty/premake5.exe -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | /.vs 3 | test/.vs 4 | test/.vscode 5 | /bin 6 | 7 | *.vcxproj 8 | *.user 9 | *.filters 10 | *.sln 11 | 12 | -------------------------------------------------------------------------------- /opengl.cpp: -------------------------------------------------------------------------------- 1 | #include "opengl.h" 2 | 3 | #define DEFINE_GL_FUNCTIONS(type, func) type func = nullptr; 4 | GL_BINDINGS(DEFINE_GL_FUNCTIONS); 5 | #undef DEFINE_GL_FUNCTIONS -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ch_stl 2 | 3 | Colby Hall's C++ Standard Library 4 | 5 | This library is in a state of constant change. It is actively iterated upon daily. 6 | 7 | This library does not use RAII. This choice was made due to the complexity of C++ RAII. You will have to manage your own resources. There are memory debugging tools though. -------------------------------------------------------------------------------- /test/ch_test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // #include 4 | 5 | // @HACK(CHall): I get it. This is bad 6 | #define TEST_FAIL(string, ...) // printf(" %i: test failed at line %i because ", test_failed + 1, __LINE__); printf(string, __VA_ARGS__); printf("\n"); test_failed += 1; 7 | #define TEST_PASS(string, ...) // printf(" "); printf(string, __VA_ARGS__); printf(" passed\n"); 8 | 9 | extern int test_failed; -------------------------------------------------------------------------------- /time.cpp: -------------------------------------------------------------------------------- 1 | #include "time.h" 2 | 3 | ch::Scoped_Timer_Manager ch::scoped_timer_manager; 4 | 5 | ch::Scoped_Timer::Scoped_Timer(const char* _name) : start(ch::get_time_in_seconds()), name(_name) { } 6 | 7 | ch::Scoped_Timer::~Scoped_Timer() { 8 | end = ch::get_time_in_seconds(); 9 | 10 | for (ch::Scoped_Timer& it : ch::scoped_timer_manager.entries) { 11 | if (ch::streq(it.name, name)) { 12 | it = *this; 13 | return; 14 | } 15 | } 16 | 17 | ch::scoped_timer_manager.entries.push(*this); 18 | } -------------------------------------------------------------------------------- /pool_allocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "hash_table.h" 4 | 5 | namespace ch { 6 | 7 | struct Pool_Bucket { 8 | void* allocation; 9 | usize used; 10 | }; 11 | 12 | struct Pool_Allocator_Header { 13 | ch::Array buckets; 14 | usize bucket_size; 15 | 16 | CH_FORCEINLINE usize get_num_buckets() const { return buckets.count; } 17 | }; 18 | 19 | ch::Allocator make_pool_allocator(usize bucket_size, usize num_buckets); 20 | void free_pool_allocator(ch::Allocator* allocator); 21 | 22 | } -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | namespace ch { 6 | using Hash_Function = u64(*)(const void* s, usize count); 7 | 8 | const u64 FNV_offset_basic = 0xcbf29ce484222325; 9 | const u64 FNV_prime = 0x100000001b3; 10 | 11 | CH_FORCEINLINE u64 fnv1_hash(const void* s, usize count) { 12 | u64 hash = ch::FNV_offset_basic; 13 | u8* casted_s = (u8*)s; 14 | for (usize i = 0; i < count; i++) { 15 | hash *= ch::FNV_prime; 16 | hash = hash ^ casted_s[i]; 17 | } 18 | 19 | return hash; 20 | } 21 | } -------------------------------------------------------------------------------- /win32/memory_win32.cpp: -------------------------------------------------------------------------------- 1 | #include "../memory.h" 2 | 3 | #if !CH_PLATFORM_WINDOWS 4 | #error This should not be compiling on this platform 5 | #endif 6 | 7 | #define WIN32_MEAN_AND_LEAN 8 | #define WIN32_LEAN_AND_MEAN 9 | #define NOMINMAX 10 | #include 11 | 12 | void* ch::malloc(usize size) { 13 | return HeapAlloc(GetProcessHeap(), 0, size); 14 | } 15 | 16 | void* ch::realloc(void* ptr, usize size) { 17 | return HeapReAlloc(GetProcessHeap(), 0, ptr, size); 18 | } 19 | 20 | void ch::free(void* ptr) { 21 | HeapFree(GetProcessHeap(), 0, ptr); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /test/premake5.lua: -------------------------------------------------------------------------------- 1 | workspace "ch_stl_test" 2 | architecture "x64" 3 | startproject "ch_test" 4 | 5 | configurations 6 | { 7 | "Debug", 8 | "Release" 9 | } 10 | 11 | targetdir ("../bin") 12 | objdir ("../bin") 13 | debugdir ("../bin") 14 | characterset ("ascii") 15 | 16 | include ".." 17 | 18 | project "ch_test" 19 | kind "ConsoleApp" 20 | language "C++" 21 | 22 | dependson 23 | { 24 | "ch_stl" 25 | } 26 | 27 | files 28 | { 29 | "*.h", 30 | "*.cpp" 31 | } 32 | 33 | links 34 | { 35 | "../bin/ch_stl.lib", 36 | 37 | } 38 | 39 | includedirs 40 | { 41 | ".." 42 | } -------------------------------------------------------------------------------- /premake5.lua: -------------------------------------------------------------------------------- 1 | project "ch_stl" 2 | kind "StaticLib" 3 | language "C++" 4 | 5 | files 6 | { 7 | "*.h", 8 | "*.cpp", 9 | "thirdparty/*.h" 10 | } 11 | 12 | defines 13 | { 14 | "_CRT_SECURE_NO_WARNINGS", 15 | } 16 | 17 | filter "configurations:Debug" 18 | runtime "Debug" 19 | symbols "On" 20 | defines 21 | { 22 | "CH_BUILD_DEBUG#1" 23 | } 24 | 25 | filter "configurations:Release" 26 | runtime "Release" 27 | optimize "On" 28 | 29 | filter "system:windows" 30 | cppdialect "C++17" 31 | systemversion "latest" 32 | 33 | files 34 | { 35 | "win32/**.h", 36 | "win32/**.cpp", 37 | } -------------------------------------------------------------------------------- /templates.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | namespace ch { 6 | template struct remove_reference { using Type = T; }; 7 | template struct remove_reference { using Type = T; }; 8 | template struct remove_reference { using Type = T; }; 9 | 10 | template inline T&& forward(typename remove_reference::Type& t) { return static_cast(t); } 11 | template inline T&& forward(typename remove_reference::Type&& t) { return static_cast(t); } 12 | template constexpr T&& move(T& t) { return static_cast::Type&&>(t); } 13 | } 14 | -------------------------------------------------------------------------------- /os.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "string.h" 4 | 5 | #if CH_PLATFORM_WINDOWS 6 | #include "win32/os_win32.h" 7 | #else 8 | #error Platform not supported 9 | #endif 10 | 11 | namespace ch { 12 | bool copy_to_clipboard(ch::OS_Window_Handle window_handle, const void* buffer, usize size); 13 | bool copy_from_clipboard(ch::OS_Window_Handle window_handle, ch::String* out_str); 14 | 15 | struct Path; 16 | 17 | struct Library { 18 | OS_Library_Handle handle; 19 | 20 | CH_FORCEINLINE operator bool() const { 21 | return handle; 22 | } 23 | 24 | void* get_function(const char* function_name); 25 | 26 | template 27 | T get_function(const char* function_name) { 28 | return (T)get_function(function_name); 29 | } 30 | 31 | void free(); 32 | }; 33 | 34 | bool load_library(const ch::Path& path, ch::Library* lib); 35 | 36 | enum Cursor_Type { 37 | CT_Arrow, 38 | CT_Cross, 39 | CT_Hand, 40 | CT_IBeam, 41 | }; 42 | 43 | bool set_cursor(ch::Cursor_Type cursor_type); 44 | 45 | } -------------------------------------------------------------------------------- /win32/filesystem_win32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | 5 | #define MAX_PATH 260 6 | 7 | struct FILETIME { 8 | DWORD dwLowDateTime; 9 | DWORD dwHighDateTime; 10 | }; 11 | using LPFILETIME = FILETIME*; 12 | 13 | struct WIN32_FIND_DATAA { 14 | DWORD dwFileAttributes; 15 | FILETIME ftCreationTime; 16 | FILETIME ftLastAccessTime; 17 | FILETIME ftLastWriteTime; 18 | DWORD nFileSizeHigh; 19 | DWORD nFileSizeLow; 20 | DWORD dwReserved0; 21 | DWORD dwReserved1; 22 | CHAR cFileName[MAX_PATH]; 23 | CHAR cAlternateFileName[14]; 24 | }; 25 | using LPWIN32_FIND_DATAA = WIN32_FIND_DATAA*; 26 | 27 | namespace ch { 28 | const usize max_path = MAX_PATH; 29 | 30 | struct Path; 31 | 32 | struct Win32_Directory_Iterator { 33 | WIN32_FIND_DATAA find_data; 34 | HANDLE file; 35 | 36 | Win32_Directory_Iterator(); 37 | Win32_Directory_Iterator(const ch::Path& path); 38 | 39 | bool can_advance() const; 40 | void advance(); 41 | 42 | struct Directory_Result get() const; 43 | }; 44 | 45 | using Directory_Iterator = Win32_Directory_Iterator; 46 | } 47 | 48 | #undef MAX_PATH -------------------------------------------------------------------------------- /win32/opengl_win32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | #include "../os.h" 5 | 6 | #if !CH_PLATFORM_WINDOWS 7 | #error This should not be compiling on this platform 8 | #endif 9 | 10 | #define WINGDIAPI DLL_IMPORT 11 | #define APIENTRY WINAPI 12 | #define APIENTRYP APIENTRY * 13 | #define GLAPI extern 14 | 15 | using HDC = HANDLE; 16 | using HGLRC = HANDLE; 17 | using HPBUFFERARB = HANDLE; 18 | using HPBUFFEREXT = HANDLE; 19 | 20 | #define DECLARE_HANDLE(handle) typedef HANDLE handle 21 | 22 | // @HACK(CHall): To prevent windows.h include 23 | #define _INC_WINAPIFAMILY 24 | 25 | #define WINAPI_FAMILY_PARTITION(x) x 26 | #define WINAPI_PARTITION_DESKTOP 1 27 | 28 | #include 29 | 30 | 31 | using WGL_Create_Context_Attribs_ARB = HGLRC(WINAPI *)(HDC hdc, HGLRC share_context, const s32* attrib_list); 32 | using WGL_Choose_Pixel_Format_ARB = bool (WINAPI *)(HDC hdc, const s32 *int_attrib_list, const float *float_attrib_list, u32 max_formats, s32 *int_formats, u32 *num_formats); 33 | using WGL_Swap_Interval_Ext = bool (WINAPI *)(s32 interval); 34 | 35 | extern WGL_Swap_Interval_Ext wglSwapIntervalEXT; 36 | -------------------------------------------------------------------------------- /memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | namespace ch { 6 | void* malloc(usize size); 7 | void* realloc(void* ptr, usize size); 8 | void free(void* ptr); 9 | 10 | #if CH_BUILD_DEBUG 11 | void* debug_malloc(usize size, const char* file, u64 line); 12 | void* debug_realloc(void* ptr, usize size, const char* file, u64 line); 13 | void debug_free(void* ptr); 14 | 15 | usize get_total_allocated(); 16 | usize get_num_allocations(); 17 | #endif 18 | 19 | void mem_copy(void* dest, const void* src, usize size); 20 | void* mem_move(void* dest, const void* src, usize size); 21 | 22 | CH_FORCEINLINE void mem_set(void* ptr, usize size, u8 c) { 23 | u8* casted_ptr = (u8*)ptr; 24 | 25 | for (usize i = 0; i < size; i++) { 26 | casted_ptr[i] = c; 27 | } 28 | } 29 | 30 | CH_FORCEINLINE void mem_zero(void* ptr, usize size) { 31 | mem_set(ptr, size, 0); 32 | } 33 | } 34 | 35 | #define ch_new new 36 | #define ch_delete delete 37 | 38 | #if CH_BUILD_DEBUG 39 | #define ch_malloc(size) ch::debug_malloc(size, __FILE__, __LINE__) 40 | #define ch_realloc(ptr, size) ch::debug_realloc(ptr, size, __FILE__, __LINE__) 41 | #define ch_free(ptr) ch::debug_free(ptr) 42 | #else 43 | #define ch_malloc(size) ch::malloc(size) 44 | #define ch_realloc(ptr, size) ch::realloc(ptr, size) 45 | #define ch_free(ptr) ch::free(ptr); 46 | #endif 47 | 48 | void* operator new(usize size); 49 | void* operator new[](usize size); 50 | 51 | void operator delete(void* ptr); 52 | void operator delete[](void* ptr); -------------------------------------------------------------------------------- /allocator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | namespace ch { 6 | /** 7 | * Allocator concept 8 | * 9 | * All actual allocator data is stored inside the allocators data as a header 10 | * We can throw this around anyway we like and it should always work 11 | */ 12 | struct Allocator { 13 | using Allocator_Func = void* (*)(const Allocator& allocator, void* ptr, usize size); 14 | 15 | u8* data; 16 | Allocator_Func func; 17 | 18 | explicit operator bool() const { 19 | return func != nullptr; 20 | } 21 | 22 | void* alloc(usize size); 23 | void* realloc(void* ptr, usize size); 24 | void free(void* ptr); 25 | 26 | template 27 | T* get_header() const { 28 | return (T*)data; 29 | } 30 | }; 31 | 32 | ch::Allocator get_heap_allocator(); 33 | 34 | struct Arena_Allocator_Header { 35 | usize allocated; 36 | usize current; 37 | void* data; 38 | }; 39 | 40 | ch::Allocator make_arena_allocator(usize size); 41 | void free_arena_allocator(ch::Allocator* allocator); 42 | void reset_arena_allocator(ch::Allocator* allocator); 43 | 44 | /** Essentially an empty allocator to prevent seg faults. */ 45 | ch::Allocator get_stack_allocator(); 46 | 47 | extern Allocator context_allocator; 48 | } 49 | 50 | void* operator new(usize size, ch::Allocator allocator); 51 | void* operator new[](usize size, ch::Allocator allocator); 52 | 53 | void operator delete(void* ptr, ch::Allocator allocator); 54 | void operator delete[](void* ptr, ch::Allocator allocator); -------------------------------------------------------------------------------- /win32/os_win32.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | 5 | using HANDLE = void*; 6 | using HINSTANCE = HANDLE; 7 | using HMODULE = HINSTANCE; 8 | using HWND = HANDLE; 9 | 10 | using BOOL = bool; 11 | using CHAR = char; 12 | using INT = s32; 13 | using UINT = u32; 14 | 15 | using LONG = long; 16 | using PLONG = LONG*; 17 | 18 | using LONGLONG = s64; 19 | using ULONGLONG = u64; 20 | 21 | #define VOID void 22 | using LPVOID = VOID*; 23 | using PVOID = VOID*; 24 | using LPCVOID = const VOID*; 25 | 26 | using LPSTR = char*; 27 | using LPCSTR = const char*; 28 | 29 | using WORD = u16; 30 | 31 | using DWORD = u32; 32 | using LPDWORD = DWORD*; 33 | 34 | using ULONG_PTR = u64; 35 | using LONG_PTR = s64; 36 | 37 | using UINT_PTR = u64; 38 | 39 | using FLOAT = float; 40 | using INT64 = s64; 41 | using INT32 = s32; 42 | using USHORT = u16; 43 | 44 | union LARGE_INTEGER { 45 | struct { 46 | DWORD LowPart; 47 | LONG HighPart; 48 | }; 49 | struct u { 50 | DWORD LowPart; 51 | LONG HighPart; 52 | }; 53 | LONGLONG QuadPart; 54 | }; 55 | using PLARGE_INTEGER = LARGE_INTEGER*; 56 | 57 | union ULARGE_INTEGER { 58 | struct { 59 | DWORD LowPart; 60 | DWORD HighPart; 61 | }; 62 | struct u { 63 | DWORD LowPart; 64 | DWORD HighPart; 65 | }; 66 | ULONGLONG QuadPart; 67 | }; 68 | 69 | using HRESULT = LONG; 70 | 71 | struct RECT { 72 | LONG left; 73 | LONG top; 74 | LONG right; 75 | LONG bottom; 76 | }; 77 | 78 | using BYTE = u8; 79 | 80 | using SIZE_T = usize; 81 | 82 | #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR) - 1) 83 | #define WINAPI __stdcall 84 | 85 | #define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i)))) 86 | 87 | using LRESULT = LONG_PTR; 88 | using WPARAM = UINT_PTR; 89 | using LPARAM = LONG_PTR; 90 | 91 | extern "C" { 92 | DLL_IMPORT BOOL CloseHandle(HANDLE); 93 | DLL_IMPORT HMODULE GetModuleHandleA(LPCSTR); 94 | } 95 | 96 | namespace ch { 97 | using OS_Handle = HANDLE; 98 | using OS_Window_Handle = OS_Handle; 99 | using OS_Stream_Handle = OS_Handle; 100 | using OS_Library_Handle = OS_Handle; 101 | 102 | bool get_caret_blink_time(u32* out_ms); 103 | } -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core.h" 4 | 5 | using u8 = unsigned char; 6 | using u16 = unsigned short; 7 | using u32 = unsigned int; 8 | using u64 = unsigned long long; 9 | 10 | using s8 = signed char; 11 | using s16 = signed short; 12 | using s32 = signed int; 13 | using s64 = signed long long; 14 | 15 | #define CH_STRINGIZE(x) CH_STRINGIZE2(x) 16 | #define CH_STRINGIZE2(x) #x 17 | 18 | #define CH_LINE_STRING CH_STRINGIZE(__LINE__) 19 | #define CH_COMPILE_ERROR_BEGIN "ch_stl compile error on line " 20 | 21 | #define CH_TYPE_SIZE_ERROR CH_COMPILE_ERROR_BEGIN CH_LINE_STRING 22 | #define CH_TYPE_SIZE_COMPARE(a, b) static_assert(sizeof(a) == sizeof(b), CH_TYPE_SIZE_ERROR) 23 | #define CH_TYPE_SIZE_LITERAL(a, b) static_assert(sizeof(a) == b, CH_TYPE_SIZE_ERROR) 24 | 25 | CH_TYPE_SIZE_COMPARE(u8, s8); 26 | CH_TYPE_SIZE_COMPARE(u16, s16); 27 | CH_TYPE_SIZE_COMPARE(u32, s32); 28 | CH_TYPE_SIZE_COMPARE(u64, s64); 29 | 30 | CH_TYPE_SIZE_LITERAL(u8, 1); 31 | CH_TYPE_SIZE_LITERAL(u16, 2); 32 | CH_TYPE_SIZE_LITERAL(u32, 4); 33 | CH_TYPE_SIZE_LITERAL(u64, 8); 34 | 35 | #if CH_PLATFORM_64BIT 36 | using usize = u64; 37 | using ssize = s64; 38 | #else 39 | using usize = u32; 40 | using ssize = s32; 41 | #endif 42 | 43 | using f32 = float; 44 | using f64 = double; 45 | 46 | CH_TYPE_SIZE_LITERAL(f32, 4); 47 | CH_TYPE_SIZE_LITERAL(f64, 8); 48 | 49 | #define U8_MIN 0u 50 | #define U8_MAX 0xffu 51 | #define U16_MIN 0u 52 | #define U16_MAX 0xffffu 53 | #define U32_MIN 0u 54 | #define U32_MAX 0xffffffffu 55 | #define U64_MIN 0ull 56 | #define U64_MAX 0xffffffffffffffffull 57 | 58 | #define S8_MIN (-0x7f - 1) 59 | #define S8_MAX 0x7f 60 | #define S16_MIN (-0x7fff - 1) 61 | #define S16_MAX 0x7fff 62 | #define S32_MIN (-0x7fffffff - 1) 63 | #define S32_MAX 0x7fffffff 64 | #define S64_MIN (-0x7fffffffffffffffll - 1) 65 | #define S64_MAX 0x7fffffffffffffffll 66 | 67 | #define F32_MIN 1.17549435e-38f 68 | #define F32_MAX 3.40282347e+38f 69 | 70 | #define F64_MIN 2.2250738585072014e-308 71 | #define F64_MAX 1.7976931348623157e+308 72 | 73 | #undef CH_STRINGIZE 74 | #undef CH_STRINGIZE2 75 | 76 | #undef CH_LINE_STRING 77 | #undef CH_COMPILE_ERROR_BEGIN 78 | 79 | #undef CH_TYPE_SIZE_ERROR 80 | #undef CH_TYPE_SIZE_COMPARE 81 | #undef CH_TYPE_SIZE_LITERAL 82 | -------------------------------------------------------------------------------- /win32/time_win32.cpp: -------------------------------------------------------------------------------- 1 | #include "../time.h" 2 | 3 | #if !CH_PLATFORM_WINDOWS 4 | #error This should not be compiling on this platform 5 | #endif 6 | 7 | struct SYSTEMTIME { 8 | WORD wYear; 9 | WORD wMonth; 10 | WORD wDayOfWeek; 11 | WORD wDay; 12 | WORD wHour; 13 | WORD wMinute; 14 | WORD wSecond; 15 | WORD wMilliseconds; 16 | }; 17 | using LPSYSTEMTIME = SYSTEMTIME*; 18 | 19 | extern "C" { 20 | DLL_IMPORT BOOL WINAPI QueryPerformanceFrequency(LARGE_INTEGER*); 21 | DLL_IMPORT BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER*); 22 | DLL_IMPORT ULONGLONG WINAPI GetTickCount64(VOID); 23 | DLL_IMPORT BOOL WINAPI FileTimeToSystemTime(const FILETIME*, LPSYSTEMTIME); 24 | DLL_IMPORT VOID WINAPI GetSystemTime(LPSYSTEMTIME); 25 | DLL_IMPORT VOID WINAPI GetLocalTime(LPSYSTEMTIME); 26 | DLL_IMPORT VOID WINAPI Sleep(DWORD); 27 | } 28 | 29 | f64 ch::get_time_in_seconds() { 30 | static LARGE_INTEGER qpc_freq; 31 | static BOOL use_qpc = QueryPerformanceFrequency(&qpc_freq); 32 | static f64 freq = (f64)qpc_freq.QuadPart; 33 | 34 | if (use_qpc) { 35 | LARGE_INTEGER now; 36 | QueryPerformanceCounter(&now); 37 | return now.QuadPart / freq; 38 | } else { 39 | return GetTickCount64() / 1000.0; 40 | } 41 | } 42 | 43 | static ch::Date_Time dt_from_win32dt(const SYSTEMTIME& st) { 44 | ch::Date_Time result; 45 | result.year = st.wYear; 46 | result.month = st.wMonth; 47 | result.day_of_week = st.wDayOfWeek; 48 | result.day_of_month = st.wDay; 49 | result.hour = st.wHour; 50 | result.minute = st.wMinute; 51 | result.second = st.wSecond; 52 | result.milliseconds = st.wMilliseconds; 53 | 54 | return result; 55 | } 56 | 57 | bool ch::date_time_from_file_time(u64 file_time, Date_Time* out_time) { 58 | SYSTEMTIME st; 59 | ULARGE_INTEGER uli; 60 | uli.QuadPart = file_time; 61 | FILETIME ft = {uli.LowPart, uli.HighPart}; 62 | if (!FileTimeToSystemTime(&ft, &st)) return false; 63 | 64 | *out_time = dt_from_win32dt(st); 65 | 66 | return true; 67 | } 68 | 69 | ch::Date_Time ch::get_system_time() { 70 | SYSTEMTIME st; 71 | GetSystemTime(&st); 72 | return dt_from_win32dt(st); 73 | } 74 | 75 | ch::Date_Time ch::get_local_time() { 76 | SYSTEMTIME st; 77 | GetLocalTime(&st); 78 | return dt_from_win32dt(st); 79 | } 80 | 81 | void ch::sleep(u32 millis) { 82 | Sleep(millis); 83 | } -------------------------------------------------------------------------------- /window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "string.h" 4 | #include "math.h" 5 | 6 | namespace ch { 7 | 8 | enum Window_Style { 9 | WS_Borderless = 0x01, 10 | WS_Can_Maximize = 0x02, 11 | WS_Can_Minimize = 0x04, 12 | WS_Visible = 0x08, 13 | }; 14 | 15 | struct Window { 16 | void* os_handle = nullptr; 17 | u32 style = 0; 18 | ch::Vector2 min_size = (s32)800; 19 | 20 | Window() = default; 21 | 22 | explicit operator bool() const { return os_handle; } 23 | operator void*() const { return os_handle; } 24 | operator void*() { return os_handle; } 25 | 26 | bool get_mouse_position(ch::Vector2* out_pos) const; 27 | ch::Vector2 get_size() const; 28 | ch::Vector2 get_viewport_size() const; 29 | bool is_visible() const; 30 | bool has_focus() const; 31 | bool is_maximized() const; 32 | 33 | void set_visibility(bool visibility); 34 | void center_in_monitor(); 35 | void maximize(); 36 | void free(); 37 | 38 | using On_Exit_Requested = void(*)(const Window& window); 39 | On_Exit_Requested on_exit_requested = nullptr; 40 | 41 | using On_Resize = void(*)(const Window& window); 42 | On_Resize on_resize = nullptr; 43 | 44 | using On_Sizing = void(*)(const Window& window); 45 | On_Sizing on_sizing = nullptr; 46 | 47 | using On_Focus_Gained = void(*)(const Window& window); 48 | On_Focus_Gained on_focus_gained = nullptr; 49 | 50 | using On_Focus_Lost = void(*)(const Window& window); 51 | On_Focus_Lost on_focus_lost = nullptr; 52 | 53 | using On_Mouse_Button_Down = void(*)(const Window& window, u8 mouse_button); 54 | On_Mouse_Button_Down on_mouse_button_down = nullptr; 55 | 56 | using On_Mouse_Button_Up = void(*)(const Window& window, u8 mouse_button); 57 | On_Mouse_Button_Up on_mouse_button_up = nullptr; 58 | 59 | using On_Key_Pressed = void(*)(const Window& window, u8 key); 60 | On_Key_Pressed on_key_pressed = nullptr; 61 | 62 | using On_Key_Released = void(*)(const Window& window, u8 key); 63 | On_Key_Released on_key_released = nullptr; 64 | 65 | using On_Char_Entered = void(*)(const Window& window, u32 c); 66 | On_Char_Entered on_char_entered = nullptr; 67 | 68 | using On_Mouse_Wheel_Scrolled = void(*)(const Window& window, f32 delta); 69 | On_Mouse_Wheel_Scrolled on_mouse_wheel_scrolled = nullptr; 70 | 71 | using On_Maximized = void(*)(const Window& window); 72 | On_Maximized on_maximized = nullptr; 73 | }; 74 | 75 | bool create_window(const char* title, u32 width, u32 height, u32 style, ch::Window* out_window); 76 | void poll_events(); 77 | void wait_events(); 78 | } -------------------------------------------------------------------------------- /win32/os_win32.cpp: -------------------------------------------------------------------------------- 1 | #include "../os.h" 2 | #include "../memory.h" 3 | #include "../filesystem.h" 4 | 5 | using HGLOBAL = HANDLE; 6 | 7 | #define INFINITE 0xFFFFFFFF 8 | #define GMEM_MOVEABLE 0x02 9 | #define CF_TEXT 1 10 | 11 | extern "C" { 12 | DLL_IMPORT UINT WINAPI GetCaretBlinkTime(VOID); 13 | DLL_IMPORT HGLOBAL WINAPI GlobalAlloc(UINT, SIZE_T); 14 | DLL_IMPORT LPVOID WINAPI GlobalLock(HGLOBAL); 15 | DLL_IMPORT BOOL WINAPI GlobalUnlock(HGLOBAL); 16 | DLL_IMPORT HGLOBAL WINAPI GlobalFree(HGLOBAL); 17 | 18 | DLL_IMPORT BOOL WINAPI OpenClipboard(HWND); 19 | DLL_IMPORT BOOL WINAPI EmptyClipboard(VOID); 20 | DLL_IMPORT HANDLE WINAPI SetClipboardData(UINT, HANDLE); 21 | DLL_IMPORT BOOL WINAPI CloseClipboard(VOID); 22 | DLL_IMPORT HANDLE WINAPI GetClipboardData(UINT); 23 | 24 | DLL_IMPORT void* WINAPI GetProcAddress(HMODULE, LPCSTR); 25 | DLL_IMPORT BOOL WINAPI FreeLibrary(HMODULE); 26 | DLL_IMPORT HMODULE WINAPI LoadLibraryA(LPCSTR); 27 | } 28 | 29 | bool ch::get_caret_blink_time(u32* out_ms) { 30 | const u32 blink_time = GetCaretBlinkTime(); 31 | if (blink_time == INFINITE) return false; 32 | 33 | *out_ms = blink_time; 34 | return true; 35 | } 36 | 37 | bool ch::copy_to_clipboard(ch::OS_Window_Handle window_handle, const void* buffer, usize size) { 38 | HGLOBAL g_mem = GlobalAlloc(GMEM_MOVEABLE, size); 39 | ch::mem_copy(GlobalLock(g_mem), buffer, size); 40 | GlobalUnlock(g_mem); 41 | if (!OpenClipboard((HWND)window_handle)) { 42 | GlobalFree(g_mem); 43 | return false; 44 | } 45 | EmptyClipboard(); 46 | SetClipboardData(CF_TEXT, g_mem); 47 | CloseClipboard(); 48 | return true; 49 | } 50 | 51 | bool ch::copy_from_clipboard(ch::OS_Window_Handle window_handle, ch::String* out_str) { 52 | if (!OpenClipboard((HWND)window_handle)) { 53 | return false; 54 | } 55 | 56 | defer(CloseClipboard()); 57 | 58 | HANDLE c_data = GetClipboardData(CF_TEXT); 59 | if (!c_data) return false; 60 | 61 | char* out_data = (char*)GlobalLock(c_data); 62 | if (!out_data) return false; 63 | 64 | const usize str_size = ch::strlen(out_data); 65 | out_str->reserve(str_size); 66 | 67 | ch::mem_copy(out_str->data, out_data, str_size * sizeof(char)); 68 | out_str->data[str_size] = 0; 69 | out_str->count = str_size; 70 | 71 | GlobalUnlock(c_data); 72 | 73 | return true; 74 | } 75 | 76 | 77 | void* ch::Library::get_function(const char* function_name) { 78 | return GetProcAddress((HMODULE)handle, function_name); 79 | } 80 | 81 | void ch::Library::free() { 82 | if (handle) { 83 | FreeLibrary((HMODULE)handle); 84 | } 85 | } 86 | 87 | bool ch::load_library(const ch::Path& path, ch::Library* lib) { 88 | ch::OS_Library_Handle handle = LoadLibraryA(path); 89 | if (handle == INVALID_HANDLE_VALUE) return false; 90 | lib->handle = handle; 91 | return true; 92 | } -------------------------------------------------------------------------------- /allocator.cpp: -------------------------------------------------------------------------------- 1 | #include "allocator.h" 2 | #include "memory.h" 3 | 4 | void* ch::Allocator::alloc(usize size) { 5 | return func(*this, nullptr, size); 6 | } 7 | 8 | void* ch::Allocator::realloc(void* ptr, usize size) { 9 | return func(*this, ptr, size); 10 | } 11 | 12 | void ch::Allocator::free(void* ptr) { 13 | func(*this, ptr, 0); 14 | } 15 | 16 | static void* heap_alloc(const ch::Allocator& allocator, void* ptr, usize size) { 17 | void* result = nullptr; 18 | if (size) { 19 | if (!ptr) { 20 | result = ch_malloc(size); 21 | } else { 22 | result = ch_realloc(ptr, size); 23 | } 24 | } else if (ptr) { 25 | ch_free(ptr); 26 | } 27 | 28 | return result; 29 | } 30 | 31 | // Use static initializer to avoid the static initialization order fiasco 32 | ch::Allocator ch::context_allocator = { nullptr, heap_alloc }; 33 | 34 | ch::Allocator ch::get_heap_allocator() { 35 | ch::Allocator result; 36 | result.data = nullptr; 37 | result.func = heap_alloc; 38 | return result; 39 | } 40 | 41 | static void* arena_alloc(const ch::Allocator& allocator, void* ptr, usize size) { 42 | ch::Arena_Allocator_Header* header = allocator.get_header(); 43 | 44 | if (!ptr || (ptr && size > 0)) { 45 | // @NOTE(Colby): this will assert if we're trying to free with a nullptr 46 | assert(size > 0); 47 | assert(header->current + size <= header->allocated); 48 | u8* result = (u8*)header->data + header->current; 49 | 50 | if (ptr) { 51 | ch::mem_copy(result, ptr, size); 52 | } 53 | 54 | header->current += size; 55 | return result; 56 | } 57 | 58 | return nullptr; 59 | } 60 | 61 | ch::Allocator ch::make_arena_allocator(usize size) { 62 | u8* data = (u8*)ch_malloc(size + sizeof(ch::Arena_Allocator_Header)); 63 | ch::Arena_Allocator_Header* header = (ch::Arena_Allocator_Header*)data; 64 | *header = {}; 65 | header->data = data + sizeof(ch::Arena_Allocator_Header); 66 | header->allocated = size; 67 | 68 | return { data, arena_alloc }; 69 | } 70 | 71 | void ch::free_arena_allocator(ch::Allocator* allocator) { 72 | ch::Arena_Allocator_Header* header = allocator->get_header(); 73 | ch_free(allocator->data); 74 | allocator->data = nullptr; 75 | } 76 | 77 | void ch::reset_arena_allocator(ch::Allocator* allocator) { 78 | ch::Arena_Allocator_Header* header = allocator->get_header(); 79 | header->current = 0; 80 | } 81 | 82 | static void* stack_alloc(const ch::Allocator& allocator, void* ptr, usize size) { return ptr; } 83 | 84 | ch::Allocator ch::get_stack_allocator() { 85 | return { nullptr, stack_alloc }; 86 | } 87 | 88 | void* operator new(usize size, ch::Allocator allocator) { 89 | return allocator.alloc(size); 90 | } 91 | 92 | void* operator new[](usize size, ch::Allocator allocator) { 93 | return allocator.alloc(size); 94 | } 95 | 96 | void operator delete(void* ptr, ch::Allocator allocator) { 97 | return allocator.free(ptr); 98 | } 99 | 100 | void operator delete[](void* ptr, ch::Allocator allocator) { 101 | return allocator.free(ptr); 102 | } -------------------------------------------------------------------------------- /time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | #include "filesystem.h" 5 | 6 | namespace ch { 7 | 8 | enum DT_Month { 9 | DTM_January = 1, 10 | DTM_February, 11 | DTM_March, 12 | DTM_April, 13 | DTM_May, 14 | DTM_June, 15 | DTM_July, 16 | DTM_August, 17 | DTM_September, 18 | DTM_October, 19 | DTM_November, 20 | DTM_December, 21 | }; 22 | 23 | enum DT_Days_Of_Week { 24 | DTDOW_Sunday = 0, 25 | DTDOW_Monday, 26 | DTDOW_Tuesday, 27 | DTDOW_Wednesday, 28 | DTDOW_Thursday, 29 | DTDOW_Friday, 30 | DTDOW_Saturday, 31 | }; 32 | 33 | CH_FORCEINLINE const char* get_month_string(u32 month) { 34 | switch (month) { 35 | case DTM_January: 36 | return "January"; 37 | case DTM_February: 38 | return "February"; 39 | case DTM_March: 40 | return "March"; 41 | case DTM_April: 42 | return "April"; 43 | case DTM_May: 44 | return "May"; 45 | case DTM_June: 46 | return "June"; 47 | case DTM_July: 48 | return "July"; 49 | case DTM_August: 50 | return "August"; 51 | case DTM_September: 52 | return "September"; 53 | case DTM_October: 54 | return "October"; 55 | case DTM_November: 56 | return "November"; 57 | case DTM_December: 58 | return "December"; 59 | } 60 | 61 | return nullptr; 62 | } 63 | 64 | CH_FORCEINLINE const char* get_days_of_week_string(u32 dow) { 65 | switch (dow) { 66 | case DTDOW_Sunday: 67 | return "Sunday"; 68 | case DTDOW_Monday: 69 | return "Monday"; 70 | case DTDOW_Tuesday: 71 | return "Tuesday"; 72 | case DTDOW_Wednesday: 73 | return "Wednesday"; 74 | case DTDOW_Thursday: 75 | return "Thursday"; 76 | case DTDOW_Friday: 77 | return "Friday"; 78 | case DTDOW_Saturday: 79 | return "Saturday"; 80 | } 81 | 82 | return nullptr; 83 | } 84 | 85 | struct Date_Time { 86 | u32 year; 87 | u32 month; 88 | u32 day_of_week; 89 | u32 day_of_month; 90 | u32 hour; 91 | u32 minute; 92 | u32 second; 93 | u32 milliseconds; 94 | 95 | Date_Time() = default; 96 | }; 97 | 98 | CH_FORCEINLINE ch::Stream& operator<<(ch::Stream& stream, const ch::Date_Time& dt) { 99 | stream << dt.month << '/' << dt.day_of_month << '/' << dt.year << ' ' << dt.hour << ':' << dt.minute << " (UTC)"; 100 | 101 | return stream; 102 | } 103 | 104 | bool date_time_from_file_time(u64 file_time, ch::Date_Time* out_time); 105 | 106 | ch::Date_Time get_system_time(); 107 | ch::Date_Time get_local_time(); 108 | void sleep(u32 milliseconds); 109 | 110 | f64 get_time_in_seconds(); 111 | 112 | struct Scoped_Timer { 113 | f64 start; 114 | f64 end; 115 | const char* name; 116 | 117 | CH_FORCEINLINE f64 get_gap() const { return end - start; } 118 | 119 | Scoped_Timer() = default; 120 | Scoped_Timer(const char* _name); 121 | ~Scoped_Timer(); 122 | }; 123 | 124 | #define CH_SCOPED_TIMER(name) ch::Scoped_Timer name(#name); 125 | 126 | struct Scoped_Timer_Manager { 127 | 128 | ch::Array entries; 129 | 130 | Scoped_Timer_Manager() { 131 | entries.allocator = ch::get_heap_allocator(); 132 | } 133 | 134 | CH_FORCEINLINE void reset() { entries.count = 0; } 135 | }; 136 | 137 | extern ch::Scoped_Timer_Manager scoped_timer_manager; 138 | } -------------------------------------------------------------------------------- /pool_allocator.cpp: -------------------------------------------------------------------------------- 1 | #include "pool_allocator.h" 2 | 3 | static void* pool_alloc(const ch::Allocator& allocator, void* ptr, usize size) { 4 | ch::Pool_Allocator_Header* header = allocator.get_header(); 5 | 6 | if (size) { 7 | if (!ptr) { 8 | ch::Pool_Allocator_Header* header = allocator.get_header(); 9 | 10 | ssize start_index = -1; 11 | usize space_found = 0; 12 | for (usize i = 0; i < header->buckets.count; i++) { 13 | ch::Pool_Bucket& it = header->buckets[i]; 14 | 15 | if (!it.allocation && start_index == -1) { 16 | start_index = i; 17 | } 18 | else if (it.allocation) { 19 | start_index = -1; 20 | space_found = 0; 21 | } 22 | 23 | if (start_index != -1) { 24 | space_found += 1; 25 | } 26 | 27 | if ((space_found * header->bucket_size) >= size) { 28 | break; 29 | } 30 | } 31 | 32 | if (start_index == -1 || (space_found * header->bucket_size) < size) return nullptr; 33 | 34 | void* allocation = (u8*)allocator.data + sizeof(*header) + (start_index * header->bucket_size); 35 | 36 | for (usize i = 0; i < space_found; i++) { 37 | ch::Pool_Bucket& it = header->buckets[i + start_index]; 38 | 39 | it.allocation = allocation; 40 | it.used = size > header->bucket_size ? header->bucket_size : size; 41 | size -= header->bucket_size; 42 | } 43 | 44 | return allocation; 45 | } else { 46 | usize old_size = 0; 47 | bool found_allocation = false; 48 | for (usize i = 0; i < header->buckets.count; i++) { 49 | ch::Pool_Bucket& it = header->buckets[i]; 50 | 51 | if (it.allocation == ptr) { 52 | found_allocation = true; 53 | } 54 | 55 | if (found_allocation && it.allocation && it.allocation != ptr) { 56 | break; 57 | } 58 | 59 | it.allocation = ptr; 60 | it.used = header->bucket_size; 61 | 62 | if (old_size + header->bucket_size >= size) { 63 | it.used = size - old_size; 64 | return it.allocation; 65 | } 66 | 67 | old_size += it.used; 68 | } 69 | 70 | assert(old_size < size); 71 | 72 | void* result = pool_alloc(allocator, nullptr, size); 73 | ch::mem_copy(result, ptr, old_size); 74 | pool_alloc(allocator, ptr, 0); // free 75 | return result; 76 | } 77 | } else if (ptr) { 78 | bool found_allocation = false; 79 | for (ch::Pool_Bucket& it : header->buckets) { 80 | if (it.allocation == ptr) { 81 | found_allocation = true; 82 | } 83 | 84 | if (found_allocation && it.allocation != ptr) break;; 85 | 86 | if (found_allocation) { 87 | it.allocation = nullptr; 88 | it.used = 0; 89 | } 90 | } 91 | } 92 | 93 | return nullptr; 94 | } 95 | 96 | ch::Allocator ch::make_pool_allocator(usize bucket_size, usize num_buckets) { 97 | assert(bucket_size); 98 | assert(num_buckets); 99 | 100 | using Header = ch::Pool_Allocator_Header; 101 | u8* data = (u8*)ch_malloc(sizeof(Header) + (bucket_size * num_buckets)); 102 | 103 | Header* header = (Header*)data; 104 | *header = {}; 105 | header->buckets.allocator = ch::get_heap_allocator(); 106 | header->buckets.reserve(num_buckets); 107 | header->buckets.count = num_buckets; 108 | header->bucket_size = bucket_size; 109 | 110 | for (ch::Pool_Bucket& it : header->buckets) { 111 | it = {}; 112 | } 113 | 114 | ch::Allocator result; 115 | result.data = data; 116 | result.func = pool_alloc; 117 | return result; 118 | } 119 | 120 | void ch::free_pool_allocator(Allocator* allocator) { 121 | ch::Pool_Allocator_Header* header = allocator->get_header(); 122 | header->buckets.free(); 123 | ch_free(allocator->data); 124 | allocator->data = nullptr; 125 | } 126 | 127 | -------------------------------------------------------------------------------- /gap_buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "allocator.h" 4 | 5 | namespace ch { 6 | const usize default_gap_size = 256; 7 | 8 | template 9 | struct Gap_Buffer { 10 | T* data = nullptr; 11 | usize allocated = 0; 12 | T* gap = nullptr; 13 | usize gap_size = 0; 14 | ch::Allocator allocator; 15 | 16 | CH_FORCEINLINE usize count() const { return allocated - gap_size; } 17 | 18 | CH_FORCEINLINE T& operator[](usize index) { 19 | assert(index < count()); 20 | 21 | if (data + index < gap) { 22 | return data[index]; 23 | } 24 | else { 25 | return data[index + gap_size]; 26 | } 27 | } 28 | 29 | CH_FORCEINLINE T operator[](usize index) const { 30 | assert(index < count()); 31 | 32 | if (data + index < gap) { 33 | return data[index]; 34 | } 35 | else { 36 | return data[index + gap_size]; 37 | } 38 | } 39 | 40 | CH_FORCEINLINE operator bool() const { 41 | return data && count(); 42 | } 43 | 44 | Gap_Buffer(const ch::Allocator& in_alloc = ch::context_allocator) : allocator(in_alloc) {} 45 | Gap_Buffer(usize size, const ch::Allocator& in_alloc = ch::context_allocator) : allocator(in_alloc) { 46 | if (size < default_gap_size) size = default_gap_size; 47 | allocated = size; 48 | data = (T*)allocator.alloc(allocated * sizeof(T)); 49 | assert(data); 50 | 51 | gap = data; 52 | gap_size = size; 53 | } 54 | 55 | void free() { 56 | if (data) allocator.free(data); 57 | } 58 | 59 | void resize(usize new_gap_size) { 60 | if (!data) { 61 | *this = Gap_Buffer(new_gap_size, allocator); 62 | return; 63 | } 64 | assert(data); 65 | assert(gap_size == 0); 66 | 67 | const usize old_size = allocated; 68 | const usize new_size = old_size + new_gap_size; 69 | 70 | T* old_data = data; 71 | T* new_data = (T*)allocator.realloc(old_data, new_size * sizeof(T)); 72 | assert(new_data); 73 | 74 | data = new_data; 75 | allocated = new_size; 76 | gap = (data + old_size); 77 | gap_size = new_gap_size; 78 | } 79 | 80 | void move_gap_to_index(usize index) { 81 | assert(index <= allocated); 82 | 83 | T* index_ptr = get_index_as_cursor(index); 84 | if (index_ptr == gap) return; 85 | 86 | if (index_ptr < gap) { 87 | const usize amount_to_move = gap - index_ptr; 88 | ch::mem_move(gap + gap_size - amount_to_move, index_ptr, amount_to_move * sizeof(T)); 89 | gap = index_ptr; 90 | } else { 91 | const usize amount_to_move = index_ptr - (gap + gap_size); 92 | ch::mem_move(gap, gap + gap_size, amount_to_move * sizeof(T)); 93 | gap += amount_to_move; 94 | } 95 | } 96 | 97 | T* get_index_as_cursor(usize index) { 98 | if (data + index <= gap) { 99 | return data + index; 100 | } 101 | 102 | return data + gap_size + index; 103 | } 104 | 105 | void insert(T c, usize index) { 106 | if (gap_size <= 0) { 107 | resize(default_gap_size); 108 | } 109 | 110 | move_gap_to_index(index); 111 | 112 | T* cursor = get_index_as_cursor(index); 113 | 114 | *cursor = c; 115 | gap += 1; 116 | gap_size -= 1; 117 | } 118 | 119 | void push(T c) { 120 | if (!data || !gap) { 121 | insert(c, 0); 122 | } else { 123 | insert(c, allocated - gap_size); 124 | } 125 | } 126 | 127 | void remove_at_index(usize index) { 128 | const usize buffer_count = count(); 129 | assert(index < buffer_count); 130 | 131 | move_gap_to_index(index + 1); 132 | 133 | gap -= 1; 134 | gap_size += 1; 135 | } 136 | 137 | void remove_between(usize index, usize count) { 138 | // @SPEED(CHall): this is slow 139 | for (usize i = index; i < index + count; i++) { 140 | remove_at_index(i); 141 | } 142 | } 143 | }; 144 | } -------------------------------------------------------------------------------- /input.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "core.h" 4 | 5 | #define CH_MOUSE_LEFT 0x00 6 | #define CH_MOUSE_MIDDLE 0x01 7 | #define CH_MOUSE_RIGHT 0x02 8 | 9 | #define CH_KEY_BACKSPACE 0x08 10 | #define CH_KEY_TAB 0x09 11 | #define CH_KEY_ENTER 0x0D 12 | 13 | #define CH_KEY_0 0x30 14 | #define CH_KEY_1 0x31 15 | #define CH_KEY_2 0x32 16 | #define CH_KEY_3 0x33 17 | #define CH_KEY_4 0x34 18 | #define CH_KEY_5 0x35 19 | #define CH_KEY_6 0x36 20 | #define CH_KEY_7 0x37 21 | #define CH_KEY_8 0x38 22 | #define CH_KEY_9 0x39 23 | 24 | #define CH_KEY_A 0x41 25 | #define CH_KEY_B 0x42 26 | #define CH_KEY_C 0x43 27 | #define CH_KEY_D 0x44 28 | #define CH_KEY_E 0x45 29 | #define CH_KEY_F 0x46 30 | #define CH_KEY_G 0x47 31 | #define CH_KEY_H 0x48 32 | #define CH_KEY_I 0x49 33 | #define CH_KEY_J 0x4A 34 | #define CH_KEY_K 0x4B 35 | #define CH_KEY_L 0x4C 36 | #define CH_KEY_M 0x4D 37 | #define CH_KEY_N 0x4E 38 | #define CH_KEY_O 0x4F 39 | #define CH_KEY_P 0x50 40 | #define CH_KEY_Q 0x51 41 | #define CH_KEY_R 0x52 42 | #define CH_KEY_S 0x53 43 | #define CH_KEY_T 0x54 44 | #define CH_KEY_U 0x55 45 | #define CH_KEY_V 0x56 46 | #define CH_KEY_W 0x57 47 | #define CH_KEY_X 0x58 48 | #define CH_KEY_Y 0x59 49 | #define CH_KEY_Z 0x5A 50 | 51 | #define CH_KEY_LBUTTON 0x01 52 | #define CH_KEY_RBUTTON 0x02 53 | #define CH_KEY_CANCEL 0x03 54 | #define CH_KEY_MBUTTON 0x04 55 | 56 | #define CH_KEY_ESCAPE 0x1B 57 | #define CH_KEY_SHIFT 0x10 58 | #define CH_KEY_CONTROL 0x11 59 | #define CH_KEY_MENU 0x12 60 | #define CH_KEY_ALT CH_KEY_MENU 61 | #define CH_KEY_PAUSE 0x13 62 | #define CH_KEY_CAPITAL 0x14 63 | 64 | #define CH_KEY_SPACE 0x20 65 | #define CH_KEY_PRIOR 0x21 66 | #define CH_KEY_NEXT 0x22 67 | #define CH_KEY_END 0x23 68 | #define CH_KEY_HOME 0x24 69 | #define CH_KEY_LEFT 0x25 70 | #define CH_KEY_UP 0x26 71 | #define CH_KEY_RIGHT 0x27 72 | #define CH_KEY_DOWN 0x28 73 | #define CH_KEY_SELECT 0x29 74 | #define CH_KEY_PRINT 0x2A 75 | #define CH_KEY_EXECUTE 0x2B 76 | #define CH_KEY_SNAPSHOT 0x2C 77 | #define CH_KEY_INSERT 0x2D 78 | #define CH_KEY_DELETE 0x2E 79 | #define CH_KEY_HELP 0x2F 80 | 81 | #define CH_KEY_NUMPAD0 0x60 82 | #define CH_KEY_NUMPAD1 0x61 83 | #define CH_KEY_NUMPAD2 0x62 84 | #define CH_KEY_NUMPAD3 0x63 85 | #define CH_KEY_NUMPAD4 0x64 86 | #define CH_KEY_NUMPAD5 0x65 87 | #define CH_KEY_NUMPAD6 0x66 88 | #define CH_KEY_NUMPAD7 0x67 89 | #define CH_KEY_NUMPAD8 0x68 90 | #define CH_KEY_NUMPAD9 0x69 91 | #define CH_KEY_MULTIPLY 0x6A 92 | #define CH_KEY_ADD 0x6B 93 | #define CH_KEY_SEPARATOR 0x6C 94 | #define CH_KEY_SUBTRACT 0x6D 95 | #define CH_KEY_DECIMAL 0x6E 96 | #define CH_KEY_DIVIDE 0x6F 97 | #define CH_KEY_F1 0x70 98 | #define CH_KEY_F2 0x71 99 | #define CH_KEY_F3 0x72 100 | #define CH_KEY_F4 0x73 101 | #define CH_KEY_F5 0x74 102 | #define CH_KEY_F6 0x75 103 | #define CH_KEY_F7 0x76 104 | #define CH_KEY_F8 0x77 105 | #define CH_KEY_F9 0x78 106 | #define CH_KEY_F10 0x79 107 | #define CH_KEY_F11 0x7A 108 | #define CH_KEY_F12 0x7B 109 | #define CH_KEY_F13 0x7C 110 | #define CH_KEY_F14 0x7D 111 | #define CH_KEY_F15 0x7E 112 | #define CH_KEY_F16 0x7F 113 | #define CH_KEY_F17 0x80 114 | #define CH_KEY_F18 0x81 115 | #define CH_KEY_F19 0x82 116 | #define CH_KEY_F20 0x83 117 | #define CH_KEY_F21 0x84 118 | #define CH_KEY_F22 0x85 119 | #define CH_KEY_F23 0x86 120 | #define CH_KEY_F24 0x87 121 | 122 | #define CH_KEY_NUMLOCK 0x90 123 | #define CH_KEY_SCROLL 0x91 124 | 125 | #define CH_KEY_LSHIFT 0xA0 126 | #define CH_KEY_RSHIFT 0xA1 127 | #define CH_KEY_LCONTROL 0xA2 128 | #define CH_KEY_RCONTROL 0xA3 129 | #define CH_KEY_LMENU 0xA4 130 | #define CH_KEY_RMENU 0xA5 131 | 132 | #define CH_KEY_TILDE 0xC0 -------------------------------------------------------------------------------- /memory.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "allocator.h" 3 | 4 | #if CH_BUILD_DEBUG 5 | struct Allocation_Header { 6 | void* allocation; 7 | usize size; 8 | 9 | const char* file; 10 | u64 line; 11 | 12 | Allocation_Header* parent; 13 | Allocation_Header* child; 14 | }; 15 | 16 | Allocation_Header* first_header = nullptr; 17 | usize total_allocated = 0; 18 | usize num_allocations = 0; 19 | 20 | void* ch::debug_malloc(usize size, const char* file, u64 line) { 21 | const usize orig_size = size; 22 | size += sizeof(Allocation_Header); 23 | u8* result = (u8*)ch::malloc(size); 24 | 25 | Allocation_Header* header = (Allocation_Header*)result; 26 | result += sizeof(Allocation_Header); 27 | 28 | *header = {}; 29 | header->allocation = result; 30 | header->size = orig_size; 31 | header->file = file; 32 | header->line = line; 33 | 34 | #if 0 35 | if (!first_header) { 36 | first_header = header; 37 | } else { 38 | Allocation_Header* current = first_header; 39 | while(current->child) { 40 | current = current->child; 41 | } 42 | 43 | current->child = header; 44 | header->parent = current; 45 | } 46 | #endif 47 | 48 | total_allocated += size; 49 | num_allocations += 1; 50 | 51 | return result; 52 | } 53 | 54 | void* ch::debug_realloc(void* ptr, usize size, const char* file, u64 line) { 55 | if (!ptr) return ch::debug_malloc(size, file, line); 56 | 57 | Allocation_Header* old_header = (Allocation_Header*)((u8*)ptr - sizeof(Allocation_Header)); 58 | const usize old_size = old_header->size + sizeof(Allocation_Header); 59 | const usize allocation_size = size + sizeof(Allocation_Header); 60 | u8* result = (u8*)ch::realloc(old_header, allocation_size); 61 | 62 | Allocation_Header* header = (Allocation_Header*)result; 63 | result += sizeof(Allocation_Header); 64 | 65 | *header = {}; 66 | header->allocation = result; 67 | header->size = size; 68 | header->file = file; 69 | header->line = line; 70 | 71 | #if 0 72 | Allocation_Header *child = header->child; 73 | Allocation_Header *parent = header->parent; 74 | if (child) { 75 | assert(child->parent == old_header); 76 | child->parent = header; 77 | } 78 | 79 | if (parent) { 80 | assert(parent->child == old_header); 81 | parent->child = header; 82 | } else { 83 | assert(old_header == first_header); 84 | first_header = header; 85 | } 86 | #endif 87 | 88 | total_allocated += allocation_size - old_size; 89 | return result; 90 | } 91 | 92 | void ch::debug_free(void* ptr) { 93 | if (!ptr) return; 94 | 95 | Allocation_Header* header = (Allocation_Header*)((u8*)ptr - sizeof(Allocation_Header)); 96 | 97 | total_allocated -= header->size + sizeof(Allocation_Header); 98 | num_allocations -= 1; 99 | 100 | #if 0 101 | Allocation_Header* child = header->child; 102 | Allocation_Header* parent = header->parent; 103 | if (child) { 104 | assert(child->parent == header); 105 | if (parent) { 106 | assert(first_header != header); 107 | parent->child = child; 108 | child->parent = parent; 109 | } else { 110 | assert(first_header == header); 111 | first_header = child; 112 | child->parent = nullptr; 113 | } 114 | } else if (parent) { 115 | parent->child = nullptr; 116 | } else { 117 | assert(first_header == header); 118 | first_header = nullptr; 119 | } 120 | #endif 121 | 122 | ch::free(header); 123 | } 124 | 125 | usize ch::get_total_allocated() { 126 | return total_allocated; 127 | } 128 | 129 | usize ch::get_num_allocations() { 130 | return num_allocations; 131 | } 132 | 133 | #endif 134 | 135 | void ch::mem_copy(void* dest, const void* src, usize size) { 136 | const u8* casted_src = (u8*)src; 137 | u8* casted_dest = (u8*)dest; 138 | 139 | for (usize i = 0; i < size; i++) { 140 | casted_dest[i] = casted_src[i]; 141 | } 142 | } 143 | 144 | void* ch::mem_move(void* dest, const void* src, usize size) { 145 | if (dest == src) return dest; 146 | 147 | if (dest < src) { 148 | ch::mem_copy(dest, src, size); 149 | return dest; 150 | } 151 | 152 | const u8* casted_src = (u8*)src; 153 | u8* casted_dest = (u8*)dest; 154 | 155 | for (usize i = size; i > 0;) { 156 | i--; 157 | casted_dest[i] = casted_src[i]; 158 | } 159 | return dest; 160 | } 161 | 162 | void* operator new(usize size) { 163 | return ch_malloc(size); 164 | } 165 | 166 | void* operator new[](usize size) { 167 | return ch_malloc(size); 168 | } 169 | 170 | void operator delete(void* ptr) { 171 | ch_free(ptr); 172 | } 173 | 174 | void operator delete[](void* ptr) { 175 | ch_free(ptr); 176 | } -------------------------------------------------------------------------------- /hash_table.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "array.h" 4 | 5 | namespace ch { 6 | /** 7 | * Totally fast and efficient hash table 8 | * 9 | * All Key's passed in need a hash function 10 | */ 11 | template 12 | struct Hash_Table { 13 | struct Pair { 14 | Key key; 15 | Value value; 16 | ch::Hash_Table::Pair* next = nullptr; 17 | 18 | Pair() = default; 19 | }; 20 | 21 | ch::Array buckets; 22 | ch::Array layout; 23 | 24 | Hash_Table(const ch::Allocator& in_alloc = ch::context_allocator) : buckets(in_alloc), layout(in_alloc) {} 25 | 26 | ch::Hash_Table copy(const ch::Allocator& in_alloc = ch::context_allocator) const { 27 | ch::Hash_Table result(in_alloc); 28 | result.buckets = buckets.copy(in_alloc); 29 | result.layout = layout.copy(in_alloc); 30 | return result; 31 | } 32 | 33 | void free() { 34 | buckets.free(); 35 | layout.free(); 36 | } 37 | 38 | Pair* begin() { 39 | return buckets.data; 40 | } 41 | 42 | Pair* end() { 43 | return buckets.data + buckets.count; 44 | } 45 | 46 | const Pair* cbegin() const { 47 | return buckets.data; 48 | } 49 | 50 | const Pair* cend() const { 51 | return buckets.data + buckets.count; 52 | } 53 | 54 | operator bool() const { return buckets && layout; } 55 | bool operator==(const ch::Hash_Table& right) { return right.buckets == buckets; } 56 | bool operator!=(const ch::Hash_Table& right) { return right.buckets != buckets; } 57 | CH_FORCEINLINE Value& operator[](usize index) { return buckets[index].value; } 58 | CH_FORCEINLINE const Value& operator[](usize index) const { return buckets[index].value; } 59 | 60 | usize key_to_index(const Key& k) const{ 61 | const u64 the_hash = hash(k); 62 | return the_hash % buckets.count; 63 | } 64 | 65 | void refresh_layout() { 66 | assert(buckets && layout.allocated > 0); 67 | 68 | ch::mem_zero(layout.data, sizeof(Pair*) * layout.allocated); 69 | layout.count = 0; 70 | 71 | for (Pair& it : buckets) { 72 | const usize index = key_to_index(it.key); 73 | 74 | it.next = nullptr; 75 | 76 | // @TODO(chall): clean this up 77 | Pair** found = &layout.data[index]; 78 | if (!(*found)) { 79 | *found = ⁢ 80 | layout.count += 1; 81 | } else { 82 | while (*found) { 83 | found = &(*found)->next; 84 | } 85 | 86 | assert(!(*found)); 87 | *found = ⁢ 88 | } 89 | } 90 | } 91 | 92 | void reserve(usize size) { 93 | buckets.reserve(size); 94 | layout.reserve(size); 95 | } 96 | 97 | usize push(const Key& k, const Value& v) { 98 | Pair r; 99 | r.key = k; 100 | r.value = v; 101 | 102 | const usize result = buckets.push(r); 103 | layout.reserve(1); 104 | 105 | refresh_layout(); 106 | 107 | return result; 108 | } 109 | 110 | usize push_zero(const Key& key) { 111 | const usize result = buckets.push_empty(); 112 | buckets[result].key = key; 113 | layout.reserve(1); 114 | 115 | refresh_layout(); 116 | 117 | return result; 118 | } 119 | 120 | Value* find(const Key& key) { 121 | if (!buckets.count) return nullptr; 122 | 123 | const usize index = key_to_index(key); 124 | 125 | Pair* found = layout.data[index]; 126 | if (!found) return nullptr; 127 | 128 | if (found->key == key) return &found->value; 129 | 130 | while (found) { 131 | found = found->next; 132 | 133 | if (found && found->key == key) return &found->value; 134 | } 135 | 136 | return nullptr; 137 | } 138 | 139 | const Value* find(const Key& key) const { 140 | if (!buckets.count) return nullptr; 141 | 142 | const usize index = key_to_index(key); 143 | 144 | Pair* found = layout.data[index]; 145 | if (!found) return nullptr; 146 | 147 | if (found->key == key) return &found->value; 148 | 149 | while (found) { 150 | found = found->next; 151 | 152 | if (found && found->key == key) return &found->value; 153 | } 154 | 155 | return nullptr; 156 | } 157 | 158 | bool remove(const Key& key) { 159 | for (usize i = 0; i < buckets.count; i++) { 160 | const Pair& p = buckets[i]; 161 | if (p.key == key) { 162 | buckets.remove(i); 163 | refresh_layout(); 164 | return true; 165 | } 166 | } 167 | 168 | return false; 169 | } 170 | 171 | void remove_by_index(usize index) { 172 | assert(index < buckets.count); 173 | 174 | buckets.remove(index); 175 | refresh_layout(); 176 | } 177 | 178 | bool contains(const Key& key) { 179 | return find(key) != nullptr; 180 | } 181 | }; 182 | } -------------------------------------------------------------------------------- /filesystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "string.h" 4 | #include "os.h" 5 | #include "array.h" 6 | 7 | #if CH_PLATFORM_WINDOWS 8 | #include "win32/filesystem_win32.h" 9 | #endif 10 | 11 | namespace ch { 12 | 13 | struct Path { 14 | char data[ch::max_path + 1]; 15 | usize count = 0; 16 | usize allocated = ch::max_path + 1; 17 | 18 | Path() = default; 19 | Path(const char* in_path); 20 | Path(const ch::String& s); 21 | 22 | CH_FORCEINLINE operator const char*() const { return data; } 23 | CH_FORCEINLINE char& operator[](usize index) { 24 | assert(index < count); 25 | return data[index]; 26 | } 27 | CH_FORCEINLINE char operator[](usize index) const { 28 | assert(index < count); 29 | return data[index]; 30 | } 31 | 32 | CH_FORCEINLINE operator bool() const { return count > 0; } 33 | 34 | CH_FORCEINLINE bool operator==(const ch::Path& right) const { 35 | if (count != right.count) return false; 36 | 37 | for (usize i = 0; i < count; i++) { 38 | if (right[i] != data[i]) return false; 39 | } 40 | 41 | return true; 42 | } 43 | 44 | CH_FORCEINLINE bool operator!=(const ch::Path& right) const { 45 | return !(*this == right); 46 | } 47 | 48 | CH_FORCEINLINE void clear() { 49 | count = 0; 50 | data[0] = 0; 51 | } 52 | 53 | void append(const char* ap, bool ensure_proper = true); 54 | void remove_until_directory(); 55 | const ch::String get_extension(); 56 | const ch::String get_filename(bool with_extension = false); 57 | 58 | bool is_relative() const; 59 | CH_FORCEINLINE bool is_absolute() const { return !is_relative(); } 60 | }; 61 | // @TODO(CHall): Add in more write functions 62 | struct Stream { 63 | OS_Stream_Handle os_handle; 64 | 65 | explicit operator bool() const { return os_handle; } 66 | 67 | Stream() : os_handle(nullptr) {} 68 | Stream(OS_Stream_Handle handle) : os_handle(handle) {} 69 | 70 | Stream& write_raw(const void* ptr, usize size); 71 | Stream& operator<<(const char* c_str); 72 | Stream& operator<<(const char c); 73 | Stream& operator<<(bool b); 74 | Stream& operator<<(u8 b); 75 | Stream& operator<<(s8 b); 76 | Stream& operator<<(u16 s); 77 | Stream& operator<<(s16 s); 78 | Stream& operator<<(u32 uint); 79 | Stream& operator<<(s32 i); 80 | Stream& operator<<(u64 ulong); 81 | Stream& operator<<(s64 slong); 82 | Stream& operator<<(f32 f); 83 | Stream& operator<<(f64 d); 84 | 85 | template 86 | Stream& operator<<(ch::Base_String str) { 87 | write_raw(str.data, str.count * sizeof(T)); 88 | return *this; 89 | } 90 | }; 91 | 92 | extern Stream std_out; 93 | extern Stream std_err; 94 | 95 | enum File_Open_Flags { 96 | FO_Read = 0x01, 97 | FO_Write = 0x02, 98 | FO_Binary = 0x04, 99 | FO_Lock = 0x08, 100 | FO_Create = 0x10, 101 | }; 102 | 103 | // @TODO(CHall): Finish this 104 | struct File : public Stream { 105 | u32 flags; 106 | bool is_open; 107 | bool is_read_only; 108 | 109 | bool open(const char* path, u32 open_flags); 110 | bool close(); 111 | 112 | bool get_absolute_path(ch::Path* out_path) const; 113 | 114 | void read(void* dest, usize size); 115 | void seek_top(); 116 | void seek_bottom(); 117 | void seek(ssize amount); 118 | void set_end_of_file(); 119 | usize size() const; 120 | 121 | u64 get_last_write_time() const; 122 | }; 123 | 124 | struct File_Data { 125 | u8* data = nullptr; 126 | usize size = 0; 127 | ch::Allocator allocator; 128 | 129 | File_Data() : data(nullptr), size(0), allocator(ch::context_allocator) {} 130 | 131 | void free(); 132 | ch::String to_string() const; 133 | }; 134 | 135 | bool load_file_into_memory(const char* path, ch::File_Data* fd, ch::Allocator allocator = ch::context_allocator); 136 | 137 | ch::Path get_current_path(); 138 | bool set_current_path(const char* path); 139 | ch::Path get_os_font_path(); 140 | ch::Path get_app_path(); 141 | 142 | enum Directory_Result_Type { 143 | DRT_Directory, 144 | DRT_File, 145 | DRT_Other, 146 | }; 147 | 148 | struct Directory_Result { 149 | Directory_Result_Type type; 150 | 151 | u64 creation_time; 152 | u64 last_access_time; 153 | u64 last_write_time; 154 | 155 | char file_name[max_path]; 156 | usize file_size; 157 | }; 158 | 159 | struct Base_Directory_Iterator { 160 | Base_Directory_Iterator() {} 161 | 162 | void advance() {} 163 | bool can_advance() const {} 164 | 165 | Directory_Result get() {} 166 | }; 167 | 168 | struct Recursive_Directory_Iterator { 169 | ch::Array iterators; 170 | usize current_iterator; 171 | ch::Path current_path; 172 | 173 | Recursive_Directory_Iterator() : Recursive_Directory_Iterator(ch::get_current_path()) {} 174 | Recursive_Directory_Iterator(const ch::Path& path); 175 | ~Recursive_Directory_Iterator(); 176 | void advance(); 177 | bool can_advance() const; 178 | 179 | Directory_Result get(); 180 | }; 181 | 182 | } -------------------------------------------------------------------------------- /string.cpp: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | usize ch::sprintf(char* buffer, const char* fmt, ...) { 9 | va_list args; 10 | va_start(args, fmt); 11 | const usize result = (usize)vsprintf(buffer, fmt, args); 12 | va_end(args); 13 | return result; 14 | } 15 | 16 | // @NOTE(Chall): shitty but it works 17 | void ch::bytes_to_string(usize bytes, String* out_string) { 18 | auto print_to_out = [&](const char* fmt) { 19 | char buffer[1024]; 20 | const usize size = ch::sprintf(buffer, fmt, bytes); 21 | out_string->reserve(size); 22 | ch::mem_copy(out_string->data, buffer, size); 23 | out_string->count = size; 24 | }; 25 | 26 | if (bytes / 1024 > 0) { 27 | bytes /= 1024; 28 | 29 | if (bytes / 1024 > 0) { 30 | bytes /= 1024; 31 | if (bytes / 1024 > 0) { 32 | bytes /= 1024; 33 | print_to_out("%llugb"); 34 | } else { 35 | print_to_out("%llumb"); 36 | } 37 | } else { 38 | print_to_out("%llukb"); 39 | } 40 | } else { 41 | print_to_out("%llub"); 42 | } 43 | } 44 | 45 | bool ch::atof(const char* tstr, f32* f) { 46 | const f32 result = (f32)::atof(tstr); 47 | if (errno == EINVAL) { 48 | return false; 49 | } 50 | 51 | *f = result; 52 | return true; 53 | } 54 | 55 | bool ch::atoi(const char* tstr, s32* i) { 56 | const s32 result = ::atoi(tstr); 57 | if (errno == EINVAL) { 58 | return false; 59 | } 60 | 61 | *i = result; 62 | return true; 63 | } 64 | 65 | static const u8 utf8d[] = { 66 | // The first part of the table maps bytes to character classes that 67 | // to reduce the size of the transition table and create bitmasks. 68 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 69 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 70 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 71 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 72 | 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 73 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 74 | 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 75 | 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, 76 | 77 | // The second part is a transition table that maps a combination 78 | // of a state of the automaton and a character class to a state. 79 | 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, 80 | 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, 81 | 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, 82 | 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, 83 | 12,36,12,12,12,12,12,12,12,12,12,12, 84 | }; 85 | 86 | u32 ch::utf8_decode(u32* state, u32* code_p, u32 byte) { 87 | u32 type = utf8d[byte]; 88 | 89 | *code_p = (*state != ch::utf8_accept) ? (byte & 0x3fu) | (*code_p << 6) : (0xff >> type) & (byte); 90 | 91 | *state = utf8d[256 + *state + type]; 92 | return *state; 93 | } 94 | 95 | s32 ch::utf8_encode(u32 c, void* dest, u32* errors) { 96 | *errors |= ((c << 11) == 0x1b) | (c > 0x10ffff) << 1 | ((c >> 1) == 0x7fff) << 2; 97 | char len = (c > 0x7f) + (c > 0x7ff) + (c > 0xffff); 98 | char* p = (char*)dest; 99 | 100 | char head = 0xf0e0c000 >> (len << 3); 101 | p[len] = 0x80 | c & 0x3f; 102 | p[len >> 1] = 0x80 | c >> 12 & 0x3f; 103 | p[1 << len >> 2] = 0x80 | c >> 6 & 0x3f; 104 | p[0] = head | c >> len * 6 & ~head >> 1; 105 | return len + 1; 106 | } 107 | 108 | usize ch::utf8_strlen(const char* str) { 109 | usize result = 0; 110 | while (*str++) result += (*str & 0xc0) != 0x80; 111 | return result; 112 | } 113 | 114 | u32 ch::utf32_to_utf8(const ch::String_UTF32& utf32, ch::String_UTF8* out_utf8) { 115 | assert(out_utf8); 116 | if (!utf32) return 0; 117 | 118 | u8 dummy[4]; 119 | u32 errors = 0; 120 | 121 | usize reservation_amount = 0; 122 | for (usize i = 0; i < utf32.count; i += 1) { 123 | reservation_amount += ch::utf8_encode(utf32[i], dummy, &errors); 124 | } 125 | 126 | if (out_utf8->allocated < reservation_amount) { 127 | out_utf8->reserve(reservation_amount - out_utf8->allocated); 128 | } 129 | errors = 0; 130 | 131 | char* cur = out_utf8->data; 132 | char* end = out_utf8->data + out_utf8->allocated; 133 | ssize i = -1; 134 | while ((cur += utf8_encode(utf32[i += 1], cur, &errors)) < end); 135 | out_utf8->count = utf32.count; 136 | out_utf8->num_errors = errors; 137 | 138 | return errors; 139 | } 140 | 141 | bool ch::utf8_to_utf32(const ch::String_UTF8& utf8, ch::String_UTF32* out_utf32) { 142 | assert(out_utf32); 143 | if (!utf8.allocated) return true; 144 | 145 | if (out_utf32->allocated < utf8.allocated) { 146 | out_utf32->reserve(utf8.allocated - out_utf32->allocated); 147 | } 148 | 149 | u32 decoder_state = ch::utf8_accept; 150 | u32 codepoint = 0; 151 | for (usize i = 0; i < utf8.allocated; i += 1) { 152 | const u8 c = (u8)utf8.data[i]; 153 | utf8_decode(&decoder_state, &codepoint, c); 154 | 155 | if (decoder_state == ch::utf8_reject) return false; 156 | if (decoder_state != ch::utf8_accept) continue; 157 | 158 | // @TODO(CHall): Should do a push? 159 | out_utf32->data[out_utf32->count] = codepoint; 160 | out_utf32->count += 1; 161 | } 162 | 163 | return true; 164 | } 165 | -------------------------------------------------------------------------------- /core.h: -------------------------------------------------------------------------------- 1 | /* 2 | Colby Hall's standard library 3 | 4 | This library tries to replace the C++ STL without any sense of RAII. The choice for this was simple. RAII in C++ adds a lot of complexity I didn't want to deal with. 5 | 6 | LICENSE 7 | This is free and unencumbered software released into the public domain. 8 | 9 | Anyone is free to copy, modify, publish, use, compile, sell, or 10 | distribute this software, either in source code form or as a compiled 11 | binary, for any purpose, commercial or non-commercial, and by any 12 | means. 13 | 14 | In jurisdictions that recognize copyright laws, the author or authors 15 | of this software dedicate any and all copyright interest in the 16 | software to the public domain. We make this dedication for the benefit 17 | of the public at large and to the detriment of our heirs and 18 | successors. We intend this dedication to be an overt act of 19 | relinquishment in perpetuity of all present and future rights to this 20 | software under copyright law. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 26 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | For more information, please refer to 31 | 32 | CREDIT 33 | Written by Colby Hall 34 | 35 | TODO 36 | - containers 37 | - set 38 | - multithreading 39 | - thread 40 | - mutex 41 | - semaphore 42 | - allocators 43 | - stack 44 | - free list 45 | */ 46 | 47 | #pragma once 48 | 49 | 50 | #if !defined(__cplusplus) 51 | #error ch_stl only supports c++ 52 | #endif 53 | 54 | #if __cplusplus < 199711L 55 | #error ch_stl requires a c++11 compiler or greater 56 | #endif 57 | 58 | #if defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__64BIT__) || defined(__powerpc64__) || defined(__ppc64__) 59 | #define CH_PLATFORM_64BIT 1 60 | #define CH_PLATFORM_32BIT 0 61 | #else 62 | #define CH_PLATFORM_64BIT 0 63 | #define CH_PLATFORM_32BIT 1 64 | #endif 65 | 66 | #if defined(_WIN32) || defined(_WIN64) 67 | #define CH_PLATFORM_WINDOWS 1 68 | #elif defined(__APPLE__) && defined(__MACH__) 69 | #define CH_PLATFORM_OSX 1 70 | #elif defined(__unix__) 71 | #define CH_PLATFORM_UNIX 1 72 | 73 | #if defined(__linux__) 74 | #define CH_PLATFORM_LINUX 1 75 | #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 76 | #define CH_PLATFORM_FREEBSD 1 77 | #else 78 | #error This UNIX operating system is not supported 79 | #endif 80 | #else 81 | #error This operating system is not supported 82 | #endif 83 | 84 | #ifndef CH_PLATFORM_WINDOWS 85 | #define CH_PLATFORM_WINDOWS 0 86 | #endif 87 | #ifndef CH_PLATFORM_OSX 88 | #define CH_PLATFORM_OSX 0 89 | #endif 90 | #ifndef CH_PLATFORM_UNIX 91 | #define CH_PLATFORM_UNIX 0 92 | #endif 93 | #ifndef CH_PLATFORM_LINUX 94 | #define CH_PLATFORM_LINUX 0 95 | #endif 96 | #ifndef CH_PLATFORM_FREEBSD 97 | #define CH_PLATFORM_FREEBSD 0 98 | #endif 99 | 100 | #if defined(_MSC_VER) 101 | #define CH_COMPILER_MSVC 1 102 | #elif defined(__GNUC__) 103 | #define CH_COMPILER_GCC 1 104 | #elif defined(__clang__) 105 | #define CH_COMPILER_CLANG 1 106 | #else 107 | #error Unknown compiler 108 | #endif 109 | 110 | #ifndef CH_COMPILER_MSVC 111 | #define CH_COMPILER_MSVC 0 112 | #endif 113 | #ifndef CH_COMPILER_GCC 114 | #define CH_COMPILER_GCC 0 115 | #endif 116 | #ifndef CH_COMPILER_CLANG 117 | #define CH_COMPILER_CLANG 0 118 | #endif 119 | 120 | #if CH_COMPILER_MSVC 121 | #define CH_FORCEINLINE __forceinline 122 | #define DLL_IMPORT __declspec(dllimport) 123 | #define DLL_EXPORT __declspec(dllexport) 124 | #endif 125 | 126 | #ifndef CH_FORCEINLINE 127 | #define CH_FORCEINLINE inline 128 | #endif 129 | 130 | #ifdef UNICODE 131 | #define CH_UNICODE 1 132 | #endif 133 | 134 | #ifndef CH_UNICODE 135 | #define CH_UNICODE 0 136 | #endif 137 | 138 | #if CH_COMPILER_MSVC 139 | #if _MSC_VER < 1300 140 | #define ch_debug_trap __asm int 3 141 | #else 142 | #define ch_debug_trap __debugbreak() 143 | #endif 144 | #else 145 | #define ch_debug_trap __builtin_trap() 146 | #endif 147 | 148 | #ifndef CH_BUILD_DEBUG 149 | #define CH_BUILD_DEBUG 0 150 | #endif; 151 | 152 | #if CH_BUILD_DEBUG 153 | #define assert(cond) if (!(cond)) ch_debug_trap 154 | #else 155 | #pragma warning (disable : 4552) 156 | #pragma warning (disable : 4553) 157 | #pragma 158 | #define assert(cond) cond 159 | #endif 160 | 161 | #define invalid_code_path ch_debug_trap; 162 | 163 | /** 164 | * This defer was created by Iganico Castano 165 | * 166 | * http://the-witness.net/news/2012/11/scopeexit-in-c11/ 167 | */ 168 | template 169 | struct Priv_Defer { 170 | F f; 171 | Priv_Defer(F f) : f(f) {} 172 | ~Priv_Defer() { f(); } 173 | }; 174 | 175 | template 176 | Priv_Defer defer_func(F f) { 177 | return Priv_Defer(f); 178 | } 179 | 180 | #define CH_DEFER_1(x, y) x##y 181 | #define CH_DEFER_2(x, y) CH_DEFER_1(x, y) 182 | #define CH_DEFER_3(x) CH_DEFER_2(x, __COUNTER__) 183 | #define defer(code) auto CH_DEFER_3(_defer_) = defer_func([&](){code;}) 184 | -------------------------------------------------------------------------------- /array.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "allocator.h" 4 | #include "memory.h" 5 | #include "templates.h" 6 | #include 7 | 8 | namespace ch { 9 | template 10 | struct Array { 11 | T* data; 12 | usize count; 13 | usize allocated; 14 | ch::Allocator allocator; 15 | 16 | Array(const ch::Allocator& in_alloc = ch::context_allocator) : data(nullptr), count(0), allocated(0), allocator(in_alloc) {} 17 | 18 | Array(std::initializer_list init_list, const Allocator& in_alloc = ch::context_allocator) 19 | : data(nullptr), count(0), allocated(0), allocator(in_alloc) { 20 | reserve(init_list.size()); 21 | for (const T& item : init_list) { 22 | data[count] = ch::move(item); 23 | count += 1; 24 | } 25 | } 26 | 27 | explicit Array(usize amount, const ch::Allocator& in_alloc = ch::context_allocator) 28 | : data(nullptr), count(0), allocated(0), allocator(in_alloc) { 29 | reserve(amount); 30 | } 31 | 32 | Array copy(const ch::Allocator& in_alloc = ch::context_allocator) const { 33 | Array result; 34 | result.count = count; 35 | result.allocator = in_alloc; 36 | result.reserve(count); 37 | ch::mem_copy(result.data, data, count * sizeof(T)); 38 | return result; 39 | } 40 | 41 | void free() { 42 | if (data) { 43 | assert(allocator && allocated); 44 | allocator.free(data); 45 | data = nullptr; 46 | } 47 | count = 0; 48 | allocated = 0; 49 | } 50 | 51 | T* begin() { 52 | return data; 53 | } 54 | 55 | T* end() { 56 | return data + count; 57 | } 58 | 59 | const T* cbegin() const { 60 | return data; 61 | } 62 | 63 | const T* cend() const { 64 | return data + count; 65 | } 66 | 67 | operator bool() const { return data && allocated; } 68 | 69 | T& operator[](usize index) { 70 | assert(index < count); 71 | return data[index]; 72 | } 73 | 74 | const T& operator[](usize index) const { 75 | assert(index < count); 76 | return data[index]; 77 | } 78 | 79 | bool operator==(const Array& right) const { 80 | if (count != right.count) return false; 81 | 82 | for (usize i = 0; i < count; i++) { 83 | if (data[i] != right[i]) return false; 84 | } 85 | 86 | return true; 87 | } 88 | 89 | bool operator!=(const Array& right) const { 90 | return !(*this == right); 91 | } 92 | 93 | void reserve(usize size) { 94 | // @TODO(CHall): find the best way to preallocate 95 | usize new_count = allocated + size; 96 | while (allocated < new_count) { 97 | allocated += allocated >> 1; 98 | allocated += 1; 99 | } 100 | 101 | if (data) { 102 | data = (T*)allocator.realloc(data, allocated * sizeof(T)); 103 | } else { 104 | data = (T*)allocator.alloc(allocated * sizeof(T)); 105 | } 106 | } 107 | 108 | T& front() { 109 | return data[0]; 110 | } 111 | 112 | const T& front() const { 113 | return data[0]; 114 | } 115 | 116 | T& back() { 117 | return data[count - 1]; 118 | } 119 | 120 | const T& back() const { 121 | return data[count - 1]; 122 | } 123 | 124 | usize push(const T& t) { 125 | const usize old_count = count; 126 | insert(t, count); 127 | return old_count; 128 | } 129 | 130 | usize push_empty() { 131 | const usize old_count = count; 132 | insert_zero(count); 133 | return old_count; 134 | } 135 | 136 | void pop() { 137 | count -= 1; 138 | } 139 | 140 | void remove(usize index) { 141 | assert(index < count); 142 | ch::mem_move(data + index, data + index + 1, (count - index) * sizeof(T)); 143 | count -= 1; 144 | } 145 | 146 | void insert(const T& t, usize index) { 147 | if (count == allocated) { 148 | reserve(1); 149 | } 150 | 151 | if (index != count) { 152 | ch::mem_move(data + index + 1, data + index, (count - index) * sizeof(T)); 153 | } 154 | 155 | data[index] = t; 156 | count += 1; 157 | } 158 | 159 | void insert_zero(usize index) { 160 | if (count == allocated) { 161 | reserve(1); 162 | } 163 | 164 | if (index != count) { 165 | ch::mem_move(data + index + 1, data + index, (count - index) * sizeof(T)); 166 | } 167 | 168 | ch::mem_zero(data + index, sizeof(T)); 169 | count += 1; 170 | } 171 | 172 | ssize find(const T& t) const { 173 | for(usize i = 0; i < count; i++) { 174 | if (data[i] == t) { 175 | return i; 176 | } 177 | } 178 | 179 | return -1; 180 | } 181 | 182 | bool contains(const T& t) const { 183 | return find(t) != -1; 184 | } 185 | 186 | }; 187 | } -------------------------------------------------------------------------------- /win32/opengl_win32.cpp: -------------------------------------------------------------------------------- 1 | #include "../opengl.h" 2 | 3 | #include "../thirdparty/wglext.h" 4 | 5 | WGL_Create_Context_Attribs_ARB wglCreateContextAttribsARB = nullptr; 6 | WGL_Choose_Pixel_Format_ARB wglChoosePixelFormatARB = nullptr; 7 | WGL_Swap_Interval_Ext wglSwapIntervalEXT = nullptr; 8 | 9 | struct PIXELFORMATDESCRIPTOR { 10 | WORD nSize; 11 | WORD nVersion; 12 | DWORD dwFlags; 13 | BYTE iPixelType; 14 | BYTE cColorBits; 15 | BYTE cRedBits; 16 | BYTE cRedShift; 17 | BYTE cGreenBits; 18 | BYTE cGreenShift; 19 | BYTE cBlueBits; 20 | BYTE cBlueShift; 21 | BYTE cAlphaBits; 22 | BYTE cAlphaShift; 23 | BYTE cAccumBits; 24 | BYTE cAccumRedBits; 25 | BYTE cAccumGreenBits; 26 | BYTE cAccumBlueBits; 27 | BYTE cAccumAlphaBits; 28 | BYTE cDepthBits; 29 | BYTE cStencilBits; 30 | BYTE cAuxBuffers; 31 | BYTE iLayerType; 32 | BYTE bReserved; 33 | DWORD dwLayerMask; 34 | DWORD dwVisibleMask; 35 | DWORD dwDamageMask; 36 | }; 37 | using LPPIXELFORMATDESCRIPTOR = PIXELFORMATDESCRIPTOR*; 38 | 39 | #define PFD_TYPE_RGBA 0 40 | #define PFD_TYPE_COLORINDEX 1 41 | 42 | /* layer types */ 43 | #define PFD_MAIN_PLANE 0 44 | #define PFD_OVERLAY_PLANE 1 45 | #define PFD_UNDERLAY_PLANE (-1) 46 | 47 | /* PIXELFORMATDESCRIPTOR flags */ 48 | #define PFD_DOUBLEBUFFER 0x00000001 49 | #define PFD_STEREO 0x00000002 50 | #define PFD_DRAW_TO_WINDOW 0x00000004 51 | #define PFD_DRAW_TO_BITMAP 0x00000008 52 | #define PFD_SUPPORT_GDI 0x00000010 53 | #define PFD_SUPPORT_OPENGL 0x00000020 54 | #define PFD_GENERIC_FORMAT 0x00000040 55 | #define PFD_NEED_PALETTE 0x00000080 56 | #define PFD_NEED_SYSTEM_PALETTE 0x00000100 57 | #define PFD_SWAP_EXCHANGE 0x00000200 58 | #define PFD_SWAP_COPY 0x00000400 59 | #define PFD_SWAP_LAYER_BUFFERS 0x00000800 60 | #define PFD_GENERIC_ACCELERATED 0x00001000 61 | #define PFD_SUPPORT_DIRECTDRAW 0x00002000 62 | #define PFD_DIRECT3D_ACCELERATED 0x00004000 63 | #define PFD_SUPPORT_COMPOSITION 0x00008000 64 | 65 | /* PIXELFORMATDESCRIPTOR flags for use in ChoosePixelFormat only */ 66 | #define PFD_DEPTH_DONTCARE 0x20000000 67 | #define PFD_DOUBLEBUFFER_DONTCARE 0x40000000 68 | #define PFD_STEREO_DONTCARE 0x80000000 69 | 70 | extern "C" { 71 | DLL_IMPORT HDC WINAPI GetDC(HWND); 72 | DLL_IMPORT int WINAPI ReleaseDC(HWND, HDC); 73 | DLL_IMPORT int WINAPI ChoosePixelFormat(HDC, const PIXELFORMATDESCRIPTOR*); 74 | DLL_IMPORT int WINAPI DescribePixelFormat(HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); 75 | DLL_IMPORT HGLRC WINAPI wglCreateContext(HDC); 76 | DLL_IMPORT BOOL WINAPI wglDeleteContext(HGLRC); 77 | DLL_IMPORT BOOL WINAPI wglMakeCurrent(HDC, HGLRC); 78 | DLL_IMPORT void* WINAPI wglGetProcAddress(LPCSTR); 79 | DLL_IMPORT BOOL WINAPI SwapBuffers(HDC); 80 | DLL_IMPORT BOOL WINAPI SetPixelFormat(HDC, int, const PIXELFORMATDESCRIPTOR*); 81 | } 82 | 83 | bool ch::load_gl() { 84 | ch::Window fake_window; 85 | if (!ch::create_window("fake_window", 12, 12, 0, &fake_window)) return false; 86 | defer(fake_window.free()); 87 | 88 | HDC window_context = GetDC((HWND)fake_window.os_handle); 89 | defer(ReleaseDC((HWND)fake_window.os_handle, window_context)); 90 | 91 | PIXELFORMATDESCRIPTOR dpf; 92 | dpf.nSize = sizeof(dpf); 93 | dpf.nVersion = 1; 94 | dpf.iPixelType = PFD_TYPE_RGBA; 95 | dpf.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; 96 | dpf.cColorBits = 32; 97 | dpf.cDepthBits = 24; 98 | dpf.cAlphaBits = 8; 99 | dpf.iLayerType = PFD_MAIN_PLANE; 100 | 101 | const s32 suggested_pixel_format_index = ChoosePixelFormat(window_context, &dpf); 102 | 103 | DescribePixelFormat(window_context, suggested_pixel_format_index, sizeof(dpf), &dpf); 104 | SetPixelFormat(window_context, suggested_pixel_format_index, &dpf); 105 | 106 | HGLRC glrc = wglCreateContext(window_context); 107 | defer(wglDeleteContext(glrc)); 108 | 109 | if (wglMakeCurrent(window_context, glrc)) { 110 | wglChoosePixelFormatARB = (WGL_Choose_Pixel_Format_ARB)wglGetProcAddress("wglChoosePixelFormatARB"); 111 | wglCreateContextAttribsARB = (WGL_Create_Context_Attribs_ARB)wglGetProcAddress("wglCreateContextAttribsARB"); 112 | wglSwapIntervalEXT = (WGL_Swap_Interval_Ext)wglGetProcAddress("wglSwapIntervalEXT"); 113 | 114 | #define LOAD_GL_BINDINGS(type, func) func = (type)wglGetProcAddress(#func); 115 | GL_BINDINGS(LOAD_GL_BINDINGS); 116 | #undef LOAD_GL_BINDINGS 117 | 118 | wglMakeCurrent(window_context, NULL); 119 | } 120 | 121 | return ch::is_gl_loaded(); 122 | } 123 | 124 | bool ch::is_gl_loaded() { 125 | #define CHECK_GL_BINDINGS(type, func) if (!func) return false; 126 | GL_BINDINGS(CHECK_GL_BINDINGS); 127 | #undef CHECK_GL_BINDINGS 128 | return true; 129 | } 130 | 131 | bool ch::swap_buffers(OS_Window_Handle window_handle) { 132 | HDC window_context = GetDC((HWND)window_handle); 133 | defer(ReleaseDC((HWND)window_handle, window_context)); 134 | return SwapBuffers(window_context); 135 | } 136 | 137 | bool ch::create_gl_window(const char* title, u32 width, u32 height, u32 style, ch::Window* out_window) { 138 | if (!ch::create_window(title, width, height, style, out_window)) { 139 | return false; 140 | } 141 | 142 | HDC window_context = GetDC((HWND)out_window->os_handle); 143 | defer(ReleaseDC((HWND)out_window->os_handle, window_context)); 144 | const s32 attrib_list[] = 145 | { 146 | WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, 147 | WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, 148 | WGL_SUPPORT_OPENGL_ARB, GL_TRUE, 149 | WGL_DOUBLE_BUFFER_ARB, GL_TRUE, 150 | WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, 151 | WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE, 152 | WGL_COLOR_BITS_ARB, 32, 153 | WGL_DEPTH_BITS_ARB, 24, 154 | WGL_STENCIL_BITS_ARB, 8, 155 | 0, 156 | }; 157 | 158 | s32 pixel_format = 0; 159 | u32 num_formats; 160 | wglChoosePixelFormatARB(window_context, attrib_list, NULL, 1, &pixel_format, &num_formats); 161 | 162 | PIXELFORMATDESCRIPTOR spf; 163 | DescribePixelFormat(window_context, pixel_format, sizeof(spf), &spf); 164 | SetPixelFormat(window_context, pixel_format, &spf); 165 | 166 | return true; 167 | } 168 | 169 | bool ch::make_current(OS_Window_Handle window_handle) { 170 | HDC window_context = GetDC((HWND)window_handle); 171 | defer(ReleaseDC((HWND)window_handle, window_context)); 172 | 173 | const s32 win32_opengl_attribs[] = { 174 | WGL_CONTEXT_MAJOR_VERSION_ARB, 3, 175 | WGL_CONTEXT_MINOR_VERSION_ARB, 3, 176 | WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 177 | WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 178 | 0, 179 | }; 180 | 181 | 182 | HGLRC glrc = wglCreateContextAttribsARB(window_context, 0, win32_opengl_attribs); 183 | 184 | return wglMakeCurrent(window_context, glrc); 185 | } -------------------------------------------------------------------------------- /filesystem.cpp: -------------------------------------------------------------------------------- 1 | #include "filesystem.h" 2 | 3 | // @HACK(CHall): We don't need to use cstl 4 | #define _CRT_NON_CONFORMING_SWPRINTFS 5 | #include 6 | 7 | ch::Path::Path(const char* in_path) : count(ch::strlen(in_path)) { 8 | assert(ch::strlen(in_path) < ch::max_path); 9 | ch::mem_copy(data, in_path, count); 10 | data[count] = 0; 11 | } 12 | 13 | ch::Path::Path(const ch::String& s) { 14 | assert(s.count < ch::max_path); 15 | ch::mem_copy(data, s.data, s.count); 16 | 17 | count = s.count; 18 | data[count] = 0; 19 | } 20 | 21 | void ch::Path::append(const char* ap, bool ensure_proper) { 22 | usize ap_count = ch::strlen(ap); 23 | if (!ap_count) return; 24 | 25 | if (ensure_proper) { 26 | const char last = data[count - 1]; 27 | const char ap_first = ap[0]; 28 | 29 | if ((last == '\\' || last == '/') && (ap_first == '\\' || ap_first == '/')) { 30 | ap += 1; 31 | ap_count -= 1; 32 | } 33 | 34 | if ((last != '\\' && last != '/') && (ap_first != '\\' && ap_first != '/')) { 35 | data[count] = '\\'; 36 | count += 1; 37 | } 38 | } 39 | 40 | assert(ap_count + count <= allocated); 41 | 42 | for (usize i = 0; i < ap_count; i++) { 43 | data[count + i] = ap[i]; 44 | } 45 | count += ap_count; 46 | data[count] = 0; 47 | } 48 | 49 | void ch::Path::remove_until_directory() { 50 | for (usize i = count - 1; i >= 0; i--) { 51 | char c = data[i]; 52 | if (c == '\\' || c == '/') { 53 | count = i; 54 | data[count] = 0; 55 | break; 56 | } 57 | } 58 | } 59 | 60 | const ch::String ch::Path::get_extension() { 61 | for (ssize i = count - 1; i >= 0; i--) { 62 | char c = data[i]; 63 | if (c == '.' && i < (ssize)count - 1) { 64 | ch::String result; 65 | result.data = data + i + 1; 66 | result.count = count - i - 1; 67 | result.allocated = result.count; 68 | return result; 69 | } 70 | } 71 | 72 | return ch::String(); 73 | } 74 | 75 | const ch::String ch::Path::get_filename(bool with_extension) { 76 | ssize extension_loc = -1; 77 | for (ssize i = count - 1; i >= 0; i--) { 78 | char c = data[i]; 79 | if (c == '.' && i < (ssize)count - 1) { 80 | extension_loc = i; 81 | } 82 | 83 | if (c == '\\' || c == '/') { 84 | if (extension_loc > -1) { 85 | ch::String result; 86 | result.data = data + i + 1; 87 | result.count = with_extension ? (count - i) : (extension_loc - i - 1); 88 | result.allocated = result.count; 89 | result.allocator = ch::get_stack_allocator(); 90 | return result; 91 | } 92 | break; 93 | } 94 | } 95 | 96 | ch::String result; 97 | result.data = data; 98 | result.count = with_extension ? count : extension_loc; 99 | result.allocated = result.count; 100 | result.allocator = ch::get_stack_allocator(); 101 | return result; 102 | } 103 | 104 | ch::Stream& ch::Stream::operator<<(bool b) { 105 | *this << (b ? "true" : "false"); 106 | return *this; 107 | } 108 | 109 | ch::Stream& ch::Stream::operator<<(u8 b) { 110 | char buffer[5]; 111 | const usize size = ch::sprintf(buffer, "%u", b); 112 | 113 | write_raw(buffer, size); 114 | return *this; 115 | } 116 | 117 | ch::Stream& ch::Stream::operator<<(s8 b) { 118 | char buffer[5]; 119 | const usize size = ch::sprintf(buffer, "%i", b); 120 | 121 | write_raw(buffer, size); 122 | return *this; 123 | } 124 | 125 | ch::Stream& ch::Stream::operator<<(u16 s) { 126 | char buffer[10]; 127 | const usize size = ch::sprintf(buffer, "%u", s); 128 | 129 | write_raw(buffer, size); 130 | return *this; 131 | } 132 | 133 | ch::Stream& ch::Stream::operator<<(s16 s) { 134 | char buffer[10]; 135 | const usize size = ch::sprintf(buffer, "%i", s); 136 | 137 | write_raw(buffer, size); 138 | return *this; 139 | } 140 | 141 | ch::Stream& ch::Stream::operator<<(u32 uint) { 142 | char buffer[32]; 143 | const usize size = ch::sprintf(buffer, "%u", uint); 144 | 145 | write_raw(buffer, size); 146 | return *this; 147 | } 148 | 149 | ch::Stream& ch::Stream::operator<<(s32 i) { 150 | char buffer[32]; 151 | const usize size = ch::sprintf(buffer, "%i", i); 152 | 153 | write_raw(buffer, size); 154 | return *this; 155 | } 156 | 157 | ch::Stream& ch::Stream::operator<<(u64 ulong) { 158 | char buffer[64]; 159 | const usize size = ch::sprintf(buffer, "%llu", ulong); 160 | 161 | write_raw(buffer, size); 162 | return *this; 163 | } 164 | 165 | ch::Stream& ch::Stream::operator<<(s64 slong) { 166 | char buffer[64]; 167 | const usize size = ch::sprintf(buffer, "%lli", slong); 168 | 169 | write_raw(buffer, size); 170 | return *this; 171 | } 172 | 173 | ch::Stream& ch::Stream::operator<<(f32 f) { 174 | char buffer[100]; 175 | const usize size = ch::sprintf(buffer, "%f", f); 176 | 177 | write_raw(buffer, size); 178 | return *this; 179 | } 180 | 181 | ch::Stream& ch::Stream::operator<<(f64 d) { 182 | char buffer[100]; 183 | const usize size = ch::sprintf(buffer, "%f", d); 184 | 185 | write_raw(buffer, size); 186 | return *this; 187 | } 188 | 189 | bool ch::load_file_into_memory(const char* path, File_Data* fd, ch::Allocator allocator) { 190 | ch::File f; 191 | defer(f.close()); 192 | if (!f.open(path, ch::FO_Read | ch::FO_Binary)) return false; 193 | 194 | const usize fs = f.size(); 195 | fd->allocator = allocator; 196 | fd->size = fs + 1; 197 | fd->data = ch_new(allocator) u8[fd->size]; 198 | f.read(fd->data, fs); 199 | fd->data[fs] = 0; 200 | 201 | return true; 202 | } 203 | 204 | void ch::File_Data::free() { 205 | if (data) { 206 | operator ch_delete(data, allocator); 207 | } 208 | } 209 | 210 | 211 | ch::String ch::File_Data::to_string() const { 212 | ch::String result; 213 | result.reserve(size); 214 | result.count = size - 1; 215 | ch::mem_copy(result.data, data, size); 216 | 217 | return result; 218 | } 219 | 220 | ch::Recursive_Directory_Iterator::Recursive_Directory_Iterator(const ch::Path& path) { 221 | current_path = path; 222 | Directory_Iterator iter(path); 223 | iterators.push(iter); 224 | } 225 | 226 | ch::Recursive_Directory_Iterator::~Recursive_Directory_Iterator() { 227 | iterators.free(); 228 | } 229 | 230 | void ch::Recursive_Directory_Iterator::advance() { 231 | ch::Directory_Iterator& current = iterators.back(); 232 | current.advance(); 233 | 234 | while (iterators.count > 1 && !current.can_advance()) { 235 | iterators.pop(); 236 | current = iterators.back(); 237 | current_path.remove_until_directory(); 238 | current.advance(); 239 | } 240 | 241 | if (current.can_advance()) { 242 | ch::Directory_Result r = current.get(); 243 | if (r.type == DRT_Directory && r.file_name[0] != '.') { 244 | current_path.append("\\"); 245 | current_path.append(r.file_name); 246 | ch::Directory_Iterator iter(current_path); 247 | iterators.push(iter); 248 | } 249 | } 250 | } 251 | 252 | bool ch::Recursive_Directory_Iterator::can_advance() const { 253 | if (!iterators) return false; 254 | 255 | return iterators.back().can_advance(); 256 | } 257 | 258 | ch::Directory_Result ch::Recursive_Directory_Iterator::get() { 259 | return iterators.back().get(); 260 | } 261 | -------------------------------------------------------------------------------- /win32/window_win32.cpp: -------------------------------------------------------------------------------- 1 | #include "../window.h" 2 | #include "../input.h" 3 | 4 | #if !CH_PLATFORM_WINDOWS 5 | #error This should not be compiling on this platform 6 | #endif 7 | 8 | #define WIN32_MEAN_AND_LEAN 9 | #define WIN32_LEAN_AND_MEAN 10 | #define NOMINMAX 11 | #include 12 | 13 | 14 | #define CALL_WINDOW_EVENT(event, ...) if (window->event) window->event(*window, __VA_ARGS__) 15 | static LRESULT window_proc(HWND handle, UINT message, WPARAM w_param, LPARAM l_param) { 16 | ch::Window* window = (ch::Window*)GetWindowLongPtr(handle, GWLP_USERDATA); 17 | 18 | if (!window) { 19 | return DefWindowProc(handle, message, w_param, l_param); 20 | } 21 | 22 | // @TODO(CHall): I still need to do mouse events. and char entered 23 | switch (message) { 24 | case WM_DESTROY: 25 | CALL_WINDOW_EVENT(on_exit_requested); 26 | break; 27 | case WM_SIZE: 28 | CALL_WINDOW_EVENT(on_resize); 29 | break; 30 | case WM_SIZING: 31 | CALL_WINDOW_EVENT(on_sizing); 32 | break; 33 | case WM_SETFOCUS: 34 | CALL_WINDOW_EVENT(on_focus_gained); 35 | break; 36 | case WM_KILLFOCUS: 37 | CALL_WINDOW_EVENT(on_focus_lost); 38 | break; 39 | case WM_SYSKEYDOWN: 40 | case WM_KEYDOWN: 41 | CALL_WINDOW_EVENT(on_key_pressed, (u8)w_param); 42 | break; 43 | case WM_SYSKEYUP: 44 | case WM_KEYUP: 45 | CALL_WINDOW_EVENT(on_key_released, (u8)w_param); 46 | break; 47 | case WM_MOUSEWHEEL: 48 | CALL_WINDOW_EVENT(on_mouse_wheel_scrolled, GET_WHEEL_DELTA_WPARAM(w_param)); 49 | break; 50 | case WM_LBUTTONDOWN: 51 | SetCapture((HWND)window->os_handle); 52 | CALL_WINDOW_EVENT(on_mouse_button_down, CH_MOUSE_LEFT); 53 | break; 54 | case WM_LBUTTONUP: 55 | ReleaseCapture(); 56 | CALL_WINDOW_EVENT(on_mouse_button_up, CH_MOUSE_LEFT); 57 | break; 58 | case WM_MBUTTONDOWN: 59 | SetCapture((HWND)window->os_handle); 60 | CALL_WINDOW_EVENT(on_mouse_button_down, CH_MOUSE_MIDDLE); 61 | break; 62 | case WM_MBUTTONUP: 63 | ReleaseCapture(); 64 | CALL_WINDOW_EVENT(on_mouse_button_up, CH_MOUSE_MIDDLE); 65 | break; 66 | case WM_RBUTTONDOWN: 67 | SetCapture((HWND)window->os_handle); 68 | CALL_WINDOW_EVENT(on_mouse_button_down, CH_MOUSE_RIGHT); 69 | break; 70 | case WM_RBUTTONUP: 71 | ReleaseCapture(); 72 | CALL_WINDOW_EVENT(on_mouse_button_up, CH_MOUSE_RIGHT); 73 | break; 74 | case WM_CHAR: { 75 | // @NOTE(CHall): UTF-8 char support 76 | static u16 surrogate_pair_first = 0; 77 | u32 c = (u32)w_param; 78 | 79 | if (c < 32 && c != '\t') break; 80 | if (c == 127) break; 81 | 82 | if (c >= 0xD800 && c <= 0xDBFF) { 83 | surrogate_pair_first = c; 84 | break; 85 | 86 | } else if (c >= 0xDC00 && c <= 0xDFFF) { 87 | u32 surrogate_pair_second = c; 88 | c = 0x10000; 89 | c += (surrogate_pair_first & 0x03FF) << 10; 90 | c += (surrogate_pair_second & 0x03FF); 91 | } 92 | CALL_WINDOW_EVENT(on_char_entered, c); 93 | } break; 94 | case WM_GETMINMAXINFO: { 95 | LPMINMAXINFO lpMMI = (LPMINMAXINFO)l_param; 96 | lpMMI->ptMinTrackSize = { window->min_size.ix, window->min_size.iy }; 97 | } break; 98 | case WM_SYSCOMMAND: 99 | switch(w_param) { 100 | case SC_MAXIMIZE: 101 | CALL_WINDOW_EVENT(on_maximized); 102 | break; 103 | } 104 | break; 105 | } 106 | 107 | 108 | return DefWindowProc(handle, message, w_param, l_param); 109 | } 110 | #undef CALL_WINDOW_EVENT 111 | 112 | bool ch::create_window(const char* title, u32 width, u32 height, u32 style, Window* out_window) { 113 | assert(out_window); 114 | 115 | *out_window = {}; 116 | 117 | WNDCLASSEXA window_class = {}; 118 | window_class.cbSize = sizeof(WNDCLASSEXA); 119 | window_class.lpfnWndProc = window_proc; 120 | window_class.hInstance = GetModuleHandleA(NULL); 121 | window_class.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 122 | window_class.lpszClassName = title; 123 | window_class.hCursor = LoadCursor(NULL, IDC_ARROW); 124 | window_class.style = CS_OWNDC; 125 | 126 | if (!RegisterClassExA(&window_class)) { 127 | return false; 128 | } 129 | 130 | HWND window_handle = CreateWindowExA(0, window_class.lpszClassName, title, WS_OVERLAPPEDWINDOW, 0, 0, width, height, NULL, NULL, window_class.hInstance, NULL); 131 | if (!window_handle) { 132 | return false; 133 | } 134 | 135 | SetWindowLongPtrA(window_handle, GWLP_USERDATA, (LONG_PTR)out_window); 136 | 137 | out_window->style = style; 138 | out_window->os_handle = window_handle; 139 | 140 | const ch::Vector2 size = out_window->get_size(); 141 | const ch::Vector2 viewport_size = out_window->get_viewport_size(); 142 | SetWindowPos((HWND)out_window->os_handle, 0, 0, 0, size.ux, (size.uy - viewport_size.uy) + size.uy, SWP_NOMOVE | SWP_NOZORDER); 143 | 144 | out_window->center_in_monitor(); 145 | 146 | return true; 147 | } 148 | 149 | void ch::poll_events() { 150 | MSG msg; 151 | while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) { 152 | TranslateMessage(&msg); 153 | DispatchMessageA(&msg); 154 | } 155 | } 156 | 157 | void ch::wait_events() { 158 | MSG msg; 159 | GetMessageA(&msg, 0, 0, 0); 160 | TranslateMessage(&msg); 161 | DispatchMessageA(&msg); 162 | } 163 | 164 | bool ch::Window::get_mouse_position(ch::Vector2* out_pos) const { 165 | POINT p; 166 | if (GetCursorPos(&p)) { 167 | if (ScreenToClient((HWND)os_handle, &p)) { 168 | out_pos->ux = (u32)p.x; 169 | out_pos->uy = (u32)p.y; 170 | 171 | const ch::Vector2 client_size = get_viewport_size(); 172 | 173 | return p.x >= 0 && p.y >= 0 && (u32)p.x < client_size.ux && (u32)p.y < client_size.uy; 174 | } 175 | } 176 | 177 | return false; 178 | } 179 | 180 | ch::Vector2 ch::Window::get_size() const { 181 | RECT rect; 182 | GetWindowRect((HWND)os_handle, &rect); 183 | 184 | ch::Vector2 result; 185 | result.ux = rect.right - rect.left; 186 | result.uy = rect.bottom - rect.top; 187 | 188 | return result; 189 | } 190 | 191 | ch::Vector2 ch::Window::get_viewport_size() const { 192 | RECT rect; 193 | GetClientRect((HWND)os_handle, &rect); 194 | 195 | ch::Vector2 result; 196 | result.ux = rect.right - rect.left; 197 | result.uy = rect.bottom - rect.top; 198 | 199 | return result; 200 | } 201 | 202 | bool ch::Window::is_visible() const { 203 | return IsWindowVisible((HWND)os_handle); 204 | } 205 | 206 | bool ch::Window::has_focus() const { 207 | return GetFocus() == os_handle; 208 | } 209 | 210 | bool ch::Window::is_maximized() const { 211 | WINDOWPLACEMENT wp; 212 | GetWindowPlacement((HWND)os_handle, &wp); 213 | return (wp.showCmd & SW_MAXIMIZE) == SW_MAXIMIZE; 214 | } 215 | 216 | void ch::Window::set_visibility(bool visibility) { 217 | ShowWindow((HWND)os_handle, (visibility ? SW_SHOW : SW_HIDE)); 218 | } 219 | 220 | void ch::Window::center_in_monitor() { 221 | const u32 monitor_width = GetSystemMetrics(SM_CXSCREEN); 222 | const u32 monitor_height = GetSystemMetrics(SM_CYSCREEN); 223 | 224 | const ch::Vector2 size = get_size(); 225 | 226 | const u32 pos_x = monitor_width / 2 - size.ux / 2; 227 | const u32 pos_y = monitor_height / 2 - size.uy / 2; 228 | 229 | SetWindowPos((HWND)os_handle, 0, pos_x, pos_y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); 230 | } 231 | 232 | void ch::Window::maximize() { 233 | ShowWindow((HWND)os_handle, SW_MAXIMIZE); 234 | } 235 | 236 | void ch::Window::free() { 237 | if (os_handle) { 238 | DestroyWindow((HWND)os_handle); 239 | os_handle = nullptr; 240 | } 241 | } 242 | 243 | -------------------------------------------------------------------------------- /test/ch_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * ch_stl lib test 3 | * used to ensure code is working 4 | * currently under construction 5 | */ 6 | 7 | #include "ch_test.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "../string.h" 15 | #include "../memory.h" 16 | #include "../math.h" 17 | 18 | int test_failed = 0; 19 | 20 | static void memory_test() { 21 | const usize buffer_size = 255; 22 | u8* buffer = ch_new u8[buffer_size]; 23 | // defer(ch_delete[] buffer); 24 | 25 | const u8 set_value = 0; 26 | ch::mem_set(buffer, buffer_size, set_value); 27 | for (usize i = 0; i < buffer_size; i++) { 28 | if (buffer[i] != set_value) { 29 | TEST_FAIL("ch::memset did not set all values in buffer %i", set_value); 30 | break; 31 | } 32 | 33 | buffer[i] = (u8)i; 34 | } 35 | 36 | // @NOTE(CHall): Is this a good test? 37 | ch::mem_move(buffer, buffer + 5, 7); 38 | if (buffer[0] != 5) { 39 | TEST_FAIL("ch::memmove is broken"); 40 | } 41 | 42 | 43 | ch::Allocator arena = ch::make_arena_allocator(1024); 44 | defer(ch::destroy_arena_allocator(&arena)); 45 | { 46 | u8* foo = (u8*)arena.alloc(256); 47 | u8* bar = (u8*)arena.alloc(256); 48 | ch::Arena_Allocator_Header* header = arena.get_header(); 49 | if (header->current != 512) { 50 | TEST_FAIL("Arean allocator book keeping is off"); 51 | } else { 52 | TEST_PASS("Arena allocator book keeping"); 53 | } 54 | 55 | const usize distance = bar - foo; 56 | if (distance != 256) { 57 | TEST_FAIL("Arean allocator allocation distance makes no sense"); 58 | } else { 59 | TEST_PASS("Arena allocator allocation"); 60 | } 61 | 62 | ch::reset_arena_allocator(&arena); 63 | bar = (u8*)arena.alloc(256); 64 | if (header->current != 256) { 65 | TEST_FAIL("Arean allocator book keeping after reset is broken"); 66 | } 67 | else { 68 | TEST_PASS("Arena allocator book keeping after reset"); 69 | } 70 | 71 | if (bar != foo) { 72 | TEST_FAIL("Arena allocation after reset is not correct"); 73 | } else { 74 | TEST_PASS("Arena allocation after reset"); 75 | } 76 | } 77 | } 78 | 79 | static void array_test() { 80 | { 81 | ch::Array array; 82 | array.push(-25.f); 83 | if (array.count != 1 || array[0] != -25.f) { 84 | TEST_FAIL("Array::add is failing"); 85 | } else { 86 | TEST_PASS("Array::add"); 87 | } 88 | array.push(45.f); 89 | array.push(20.f); 90 | array.remove(1); 91 | if (array[1] != 20.f) { 92 | TEST_FAIL("Array::remove is failing to remove index 1"); 93 | } else { 94 | TEST_PASS("Array::remove"); 95 | } 96 | } 97 | 98 | { 99 | ch::Array array = { 120.f, 12.f, 5.f }; 100 | if (array[0] != 120.f || array[1] != 12.f || array[2] != 5.f) { 101 | TEST_FAIL("Array initializer list construction failed"); 102 | } else { 103 | TEST_PASS("Array initializer list"); 104 | } 105 | } 106 | } 107 | 108 | static void string_test() { 109 | ch::String foo = ch::String(CH_TEXT("hello world")); 110 | defer(foo.destroy()); 111 | ch::String bar = foo; 112 | 113 | if (foo.data != bar.data) { 114 | TEST_FAIL("String has a reallocation"); 115 | } else { 116 | TEST_PASS("String copy") 117 | } 118 | 119 | if (!foo.starts_with(CH_TEXT("hello"))) { 120 | TEST_FAIL("String starts with is broken"); 121 | } else { 122 | TEST_PASS("String starts with"); 123 | } 124 | 125 | if (!foo.starts_with(CH_TEXT("hello world"))) { 126 | TEST_FAIL("String starts with is broken"); 127 | } else { 128 | TEST_PASS("String starts with"); 129 | } 130 | 131 | if (foo.starts_with(CH_TEXT("Hello"), true)) { 132 | TEST_FAIL("String starts with is broken"); 133 | } else { 134 | TEST_PASS("String starts with"); 135 | } 136 | 137 | if (foo.starts_with(CH_TEXT("Hello world"), true)) { 138 | TEST_FAIL("String starts with is broken"); 139 | } else { 140 | TEST_PASS("String starts with"); 141 | } 142 | 143 | if (!foo.ends_with(CH_TEXT("world"))) { 144 | TEST_FAIL("String ends with is broken"); 145 | } else { 146 | TEST_PASS("String ends with"); 147 | } 148 | 149 | if (!foo.ends_with(CH_TEXT("hello world"))) { 150 | TEST_FAIL("String ends with is broken"); 151 | } else { 152 | TEST_PASS("String ends with"); 153 | } 154 | 155 | if (foo.ends_with(CH_TEXT("World"), true)) { 156 | TEST_FAIL("String ends with is broken"); 157 | } else { 158 | TEST_PASS("String ends with"); 159 | } 160 | 161 | if (foo.ends_with(CH_TEXT("Hello world"), true)) { 162 | TEST_FAIL("String ends with is broken"); 163 | } else { 164 | TEST_PASS("String ends with"); 165 | } 166 | } 167 | 168 | static void math_test() { 169 | ch::Vector2 vec = 5.f; 170 | ch::Vector2 vec_n = vec.get_normalized(); 171 | if (!vec_n.is_normalized()) { 172 | TEST_FAIL("Vec2 normalized failed"); 173 | } else { 174 | TEST_PASS("Vec2 nomalized"); 175 | } 176 | 177 | ch::Color color = 0xFF00FFFF; 178 | const s32 color_out = (s32)color; 179 | } 180 | 181 | const u32 width = 1280; 182 | const u32 height = (u32)((f32)width * (9.f / 16.f)); 183 | 184 | static void window_test() { 185 | ch::Window window; 186 | if (!ch::create_window(CH_TEXT("test window"), width, height, 0, &window)) { 187 | TEST_FAIL("Failed to create window"); 188 | return; 189 | } else { 190 | TEST_PASS("Create Window"); 191 | } 192 | defer(window.destroy()); 193 | 194 | window.set_visibility(true); 195 | 196 | if (!window.is_visible()) { 197 | TEST_FAIL("Failed to set window visibility"); 198 | } else { 199 | TEST_PASS("Setting visibility"); 200 | } 201 | } 202 | 203 | static bool exit_requested = false; 204 | 205 | static void gl_test() { 206 | if (!ch::load_gl()) { 207 | TEST_FAIL("Failed to load opengl"); 208 | return; 209 | } else { 210 | TEST_PASS("Loading opengl"); 211 | } 212 | 213 | ch::Window window; 214 | if (!ch::create_gl_window(CH_TEXT("opengl test window"), width, height, 0, &window)) { 215 | TEST_FAIL("Failed to open a gl window"); 216 | return; 217 | } else { 218 | TEST_PASS("Create GL Window"); 219 | } 220 | defer(window.destroy()); 221 | 222 | window.set_visibility(true); 223 | 224 | if (!ch::make_current(window)) { 225 | TEST_FAIL("Failed to set current gl window"); 226 | } else { 227 | TEST_PASS("Set current gl window"); 228 | } 229 | 230 | auto exit_request = [](const ch::Window& window) { 231 | exit_requested = true; 232 | }; 233 | 234 | window.on_exit_requested = exit_request; 235 | 236 | while (!exit_requested) { 237 | glClear(GL_COLOR_BUFFER_BIT); 238 | glClearColor(0.f, 1.f, 1.f, 1.f); 239 | 240 | if (!ch::swap_buffers(window)) { 241 | TEST_FAIL("failed to swap window buffer"); 242 | break; 243 | } 244 | ch::poll_events(); 245 | } 246 | 247 | TEST_PASS("Swap window buffer"); 248 | } 249 | 250 | static void fs_test() { 251 | ch::String current_path = ch::get_current_path(); 252 | if (!current_path) { 253 | TEST_FAIL("failed to get current path"); 254 | } else { 255 | TEST_PASS("get current path"); 256 | ch::std_out << current_path << ch::eol; 257 | } 258 | defer(current_path.destroy()); 259 | } 260 | 261 | int main() { 262 | // printf("-------Beginning c_stl Test-------\n"); 263 | memory_test(); 264 | array_test(); 265 | string_test(); 266 | math_test(); 267 | window_test(); 268 | gl_test(); 269 | fs_test(); 270 | // printf("-------c_stl Test Finished-------\n"); 271 | 272 | if (test_failed) { 273 | // printf("%i test failed\n\nPlease report to author(s)\n", test_failed); 274 | } 275 | 276 | for(;;) {} 277 | } -------------------------------------------------------------------------------- /win32/filesystem_win32.cpp: -------------------------------------------------------------------------------- 1 | #include "../filesystem.h" 2 | 3 | #if !CH_PLATFORM_WINDOWS 4 | #error This should not be compiling on this platform 5 | #endif 6 | 7 | struct OVERLAPPED { 8 | ULONG_PTR Internal; 9 | ULONG_PTR InternalHigh; 10 | union { 11 | struct { 12 | DWORD Offset; 13 | DWORD OffsetHigh; 14 | }; 15 | PVOID Pointer; 16 | }; 17 | 18 | HANDLE hEvent; 19 | }; 20 | 21 | using LPOVERLAPPED = OVERLAPPED*; 22 | 23 | #define STD_INPUT_HANDLE ((DWORD)-10) 24 | #define STD_OUTPUT_HANDLE ((DWORD)-11) 25 | #define STD_ERROR_HANDLE ((DWORD)-12) 26 | 27 | struct SECURITY_ATTRIBUTES { 28 | DWORD nLength; 29 | LPVOID lpSecurityDescriptor; 30 | BOOL bInheritHandle; 31 | }; 32 | 33 | using LPSECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES*; 34 | 35 | #define FILE_SHARE_READ 0x00000001 36 | #define FILE_SHARE_WRITE 0x00000002 37 | #define FILE_SHARE_DELETE 0x00000004 38 | #define FILE_ATTRIBUTE_READONLY 0x00000001 39 | #define FILE_ATTRIBUTE_HIDDEN 0x00000002 40 | #define FILE_ATTRIBUTE_SYSTEM 0x00000004 41 | #define FILE_ATTRIBUTE_DIRECTORY 0x00000010 42 | #define FILE_ATTRIBUTE_ARCHIVE 0x00000020 43 | #define FILE_ATTRIBUTE_DEVICE 0x00000040 44 | #define FILE_ATTRIBUTE_NORMAL 0x00000080 45 | #define FILE_ATTRIBUTE_TEMPORARY 0x00000100 46 | #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200 47 | #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 48 | #define FILE_ATTRIBUTE_COMPRESSED 0x00000800 49 | #define FILE_ATTRIBUTE_OFFLINE 0x00001000 50 | #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000 51 | #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000 52 | #define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x00008000 53 | #define FILE_ATTRIBUTE_VIRTUAL 0x00010000 54 | #define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x00020000 55 | #define FILE_ATTRIBUTE_EA 0x00040000 56 | #define FILE_ATTRIBUTE_PINNED 0x00080000 57 | #define FILE_ATTRIBUTE_UNPINNED 0x00100000 58 | #define FILE_ATTRIBUTE_RECALL_ON_OPEN 0x00040000 59 | #define FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS 0x00400000 60 | 61 | #define GENERIC_READ (0x80000000L) 62 | #define GENERIC_WRITE (0x40000000L) 63 | #define GENERIC_EXECUTE (0x20000000L) 64 | #define GENERIC_ALL (0x10000000L) 65 | 66 | #define CREATE_NEW 1 67 | #define CREATE_ALWAYS 2 68 | #define OPEN_EXISTING 3 69 | #define OPEN_ALWAYS 4 70 | #define TRUNCATE_EXISTING 5 71 | 72 | #define VOLUME_NAME_DOS 0x0 //default 73 | #define VOLUME_NAME_GUID 0x1 74 | #define VOLUME_NAME_NT 0x2 75 | #define VOLUME_NAME_NONE 0x4 76 | 77 | #define FILE_NAME_NORMALIZED 0x0 //default 78 | #define FILE_NAME_OPENED 0x8 79 | 80 | #define FILE_BEGIN 0 81 | #define FILE_CURRENT 1 82 | #define FILE_END 2 83 | 84 | extern "C" { 85 | DLL_IMPORT BOOL WINAPI PathIsRelativeA(LPCSTR); 86 | DLL_IMPORT HANDLE WINAPI GetStdHandle(DWORD); 87 | DLL_IMPORT BOOL WINAPI WriteFile(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED); 88 | DLL_IMPORT HANDLE WINAPI CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); 89 | DLL_IMPORT DWORD WINAPI GetFinalPathNameByHandleA(HANDLE, LPSTR, DWORD, DWORD); 90 | DLL_IMPORT BOOL WINAPI ReadFile(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED); 91 | DLL_IMPORT DWORD WINAPI SetFilePointer(HANDLE, LONG, PLONG, DWORD); 92 | DLL_IMPORT BOOL WINAPI SetEndOfFile(HANDLE); 93 | DLL_IMPORT DWORD WINAPI GetFileSize(HANDLE, LPDWORD); 94 | DLL_IMPORT BOOL WINAPI GetFileTime(HANDLE, LPFILETIME, LPFILETIME, LPFILETIME); 95 | DLL_IMPORT DWORD WINAPI GetCurrentDirectoryA(DWORD, LPSTR); 96 | DLL_IMPORT BOOL WINAPI SetCurrentDirectoryA(LPCSTR); 97 | DLL_IMPORT UINT WINAPI GetWindowsDirectoryA(LPSTR, UINT); 98 | DLL_IMPORT DWORD WINAPI GetModuleFileNameA(HMODULE, LPSTR, DWORD); 99 | DLL_IMPORT HANDLE WINAPI FindFirstFileA(LPCSTR, LPWIN32_FIND_DATAA); 100 | DLL_IMPORT BOOL WINAPI FindNextFileA(HANDLE, LPWIN32_FIND_DATAA); 101 | DLL_IMPORT DWORD WINAPI GetFileAttributesA(LPCSTR); 102 | } 103 | 104 | bool ch::Path::is_relative() const { 105 | return PathIsRelativeA(data); 106 | } 107 | 108 | ch::Stream ch::std_out = GetStdHandle(STD_OUTPUT_HANDLE); 109 | ch::Stream ch::std_err = GetStdHandle(STD_ERROR_HANDLE); 110 | 111 | ch::Stream& ch::Stream::write_raw(const void* ptr, usize size) { 112 | WriteFile(os_handle, ptr, (DWORD)size, nullptr, nullptr); 113 | return *this; 114 | } 115 | 116 | ch::Stream& ch::Stream::operator<<(const char* c_str) { 117 | return write_raw(c_str, ch::strlen(c_str) * sizeof(char)); 118 | } 119 | 120 | ch::Stream& ch::Stream::operator<<(const char c) { 121 | return write_raw(&c, sizeof(c)); 122 | } 123 | 124 | bool ch::File::open(const char* path, u32 open_flags) { 125 | flags = open_flags; 126 | const bool read = open_flags & FO_Read; 127 | const bool write = open_flags & FO_Write; 128 | const bool binary = open_flags & FO_Binary; 129 | const bool lock = open_flags & FO_Lock; 130 | const bool create = open_flags & FO_Create; 131 | 132 | assert(read || write); 133 | DWORD desired_access = 0; 134 | if (read) desired_access |= GENERIC_READ; 135 | if (write) desired_access |= GENERIC_WRITE; 136 | 137 | DWORD creation = OPEN_EXISTING; 138 | if (create) creation = CREATE_NEW; 139 | 140 | os_handle = CreateFileA(path, desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); 141 | is_open = os_handle != INVALID_HANDLE_VALUE; 142 | 143 | if (!is_open && create) { 144 | os_handle = CreateFileA(path, desired_access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 145 | is_open = os_handle != INVALID_HANDLE_VALUE; 146 | } 147 | 148 | if (is_open) { 149 | const DWORD attrib = GetFileAttributesA(path); 150 | is_read_only = attrib & FILE_ATTRIBUTE_READONLY; 151 | } 152 | 153 | return is_open; 154 | } 155 | 156 | bool ch::File::close() { 157 | if (is_open && CloseHandle(os_handle)) { 158 | is_open = false; 159 | } 160 | 161 | return !is_open; 162 | } 163 | 164 | bool ch::File::get_absolute_path(ch::Path* out_path) const { 165 | assert(is_open); 166 | out_path->count = GetFinalPathNameByHandleA(os_handle, out_path->data, (DWORD)out_path->allocated, FILE_NAME_OPENED | VOLUME_NAME_NONE); 167 | return *out_path; 168 | } 169 | 170 | void ch::File::read(void* dest, usize size) { 171 | assert(is_open); 172 | ReadFile(os_handle, dest, (DWORD)size, NULL, NULL); 173 | } 174 | 175 | void ch::File::seek_top() { 176 | assert(is_open); 177 | SetFilePointer(os_handle, NULL, NULL, FILE_BEGIN); 178 | } 179 | 180 | void ch::File::seek_bottom() { 181 | assert(is_open); 182 | SetFilePointer(os_handle, NULL, NULL, FILE_END); 183 | } 184 | 185 | void ch::File::seek(ssize amount) { 186 | assert(is_open); 187 | LARGE_INTEGER li; 188 | li.QuadPart = amount; 189 | // @NOTE(CHall): Gotta make the compiler happy 190 | SetFilePointer(os_handle, li.LowPart, (PLONG)(s64)li.HighPart, FILE_CURRENT); 191 | } 192 | 193 | void ch::File::set_end_of_file() { 194 | assert(is_open); 195 | SetEndOfFile(os_handle); 196 | } 197 | 198 | usize ch::File::size() const { 199 | assert(is_open); 200 | const DWORD file_size = GetFileSize(os_handle, NULL); 201 | 202 | return (usize)file_size; 203 | } 204 | 205 | u64 ch::File::get_last_write_time() const { 206 | assert(is_open); 207 | FILETIME creation_time; 208 | FILETIME access_time; 209 | FILETIME write_time; 210 | 211 | GetFileTime((HANDLE)os_handle, &creation_time, &access_time, &write_time); 212 | 213 | LARGE_INTEGER result; 214 | result.LowPart = write_time.dwLowDateTime; 215 | result.HighPart = write_time.dwHighDateTime; 216 | 217 | return result.QuadPart; 218 | } 219 | 220 | ch::Path ch::get_current_path() { 221 | ch::Path result; 222 | GetCurrentDirectoryA((DWORD)ch::max_path, result.data); 223 | result.count = ch::strlen(result.data); 224 | result.data[result.count] = 0; 225 | return result; 226 | } 227 | 228 | bool ch::set_current_path(const char* path) { 229 | return SetCurrentDirectoryA(path); 230 | } 231 | 232 | ch::Path ch::get_os_font_path() { 233 | ch::Path result; 234 | 235 | GetWindowsDirectoryA(result.data, (DWORD)ch::max_path); 236 | result.count = ch::strlen(result.data); 237 | result.data[result.count] = 0; 238 | 239 | result.append("Fonts"); 240 | result.data[result.count] = 0; 241 | 242 | return result; 243 | } 244 | 245 | ch::Path ch::get_app_path() { 246 | ch::Path result; 247 | GetModuleFileNameA(NULL, result.data, (DWORD)ch::max_path); 248 | result.count = ch::strlen(result.data); 249 | result.data[result.count] = 0; 250 | 251 | return result; 252 | } 253 | 254 | 255 | ch::Win32_Directory_Iterator::Win32_Directory_Iterator(const ch::Path& path) { 256 | 257 | ch::Path actual_path = path; 258 | actual_path.append("\\*"); 259 | 260 | file = FindFirstFileA(actual_path, &find_data); 261 | } 262 | 263 | ch::Win32_Directory_Iterator::Win32_Directory_Iterator() : ch::Win32_Directory_Iterator(ch::get_current_path()) {} 264 | 265 | bool ch::Win32_Directory_Iterator::can_advance() const { 266 | return file != INVALID_HANDLE_VALUE; 267 | } 268 | 269 | void ch::Win32_Directory_Iterator::advance() { 270 | if (!FindNextFileA(file, &find_data)) { 271 | file = INVALID_HANDLE_VALUE; 272 | } 273 | } 274 | 275 | ch::Directory_Result ch::Win32_Directory_Iterator::get() const { 276 | assert(can_advance()); 277 | 278 | ch::Directory_Result result; 279 | result.type = DRT_Other; 280 | 281 | switch (find_data.dwFileAttributes) { 282 | case FILE_ATTRIBUTE_DIRECTORY: 283 | result.type = DRT_Directory; 284 | break; 285 | case FILE_ATTRIBUTE_NORMAL: 286 | case FILE_ATTRIBUTE_ARCHIVE: 287 | case FILE_ATTRIBUTE_READONLY: 288 | result.type = DRT_File; 289 | break; 290 | } 291 | 292 | LARGE_INTEGER file_size; 293 | file_size.LowPart = find_data.nFileSizeLow; 294 | file_size.HighPart = find_data.nFileSizeHigh; 295 | result.file_size = file_size.QuadPart; 296 | 297 | auto FILETIME_to_u64 = [](FILETIME ft) -> u64 { 298 | ULARGE_INTEGER uli; 299 | uli.LowPart = ft.dwLowDateTime; 300 | uli.HighPart = ft.dwHighDateTime; 301 | return uli.QuadPart; 302 | }; 303 | 304 | ch::mem_copy(result.file_name, find_data.cFileName, ch::max_path); 305 | result.creation_time = FILETIME_to_u64(find_data.ftCreationTime); 306 | result.last_access_time = FILETIME_to_u64(find_data.ftLastAccessTime); 307 | result.last_write_time = FILETIME_to_u64(find_data.ftLastWriteTime); 308 | 309 | return result; 310 | } 311 | -------------------------------------------------------------------------------- /math.cpp: -------------------------------------------------------------------------------- 1 | #include "math.h" 2 | #include "hash.h" 3 | #include "filesystem.h" 4 | 5 | #include 6 | 7 | f32 ch::sqrt(f32 s) { 8 | return ::sqrtf(s); 9 | } 10 | 11 | f32 ch::cos(f32 s) { 12 | return ::cosf(s); 13 | } 14 | 15 | f32 ch::sin(f32 s) { 16 | return ::sinf(s); 17 | } 18 | 19 | f32 ch::asin(f32 s) { 20 | return asinf(s); 21 | } 22 | 23 | f32 ch::tan(f32 s) { 24 | return tanf(s); 25 | } 26 | 27 | f32 ch::atan(f32 s) { 28 | return atanf(s); 29 | } 30 | 31 | f32 ch::atan2(f32 x, f32 y) { 32 | return atan2f(x, y); 33 | } 34 | 35 | ch::Matrix4 ch::Matrix4::operator*(const Matrix4& right) const { 36 | ch::Matrix4 result = {}; 37 | for (s32 y = 0; y < 4; y++) { 38 | for (s32 x = 0; x < 4; x++) { 39 | f32 sum = 0.0f; 40 | for (s32 e = 0; e < 4; e++) { 41 | sum += elems[x + e * 4] * right[e + y * 4]; 42 | } 43 | result[x + y * 4] = sum; 44 | } 45 | } 46 | return result; 47 | } 48 | 49 | // @NOTE(Chall): I wrote this in HS idk if its bad. its late 50 | ch::Vector4 ch::Matrix4::operator*(const ch::Vector4& right) const { 51 | return ch::Vector4( 52 | rows[0].x * right.x + rows[0].y * right.y + rows[0].z * right.z + rows[0].w * right.w, 53 | rows[1].x * right.x + rows[1].y * right.y + rows[1].z * right.z + rows[1].w * right.w, 54 | rows[2].x * right.x + rows[2].y * right.y + rows[2].z * right.z + rows[2].w * right.w, 55 | rows[3].x * right.x + rows[3].y * right.y + rows[3].z * right.z + rows[3].w * right.w 56 | ); 57 | } 58 | 59 | // @NOTE(CHall): How bad is this 60 | ch::Matrix4 ch::Matrix4::inverse() { 61 | ch::Matrix4 result = *this; 62 | 63 | f32 temp[16]; 64 | 65 | temp[0] = result.elems[5] * result.elems[10] * result.elems[15] - 66 | result.elems[5] * result.elems[11] * result.elems[14] - 67 | result.elems[9] * result.elems[6] * result.elems[15] + 68 | result.elems[9] * result.elems[7] * result.elems[14] + 69 | result.elems[13] * result.elems[6] * result.elems[11] - 70 | result.elems[13] * result.elems[7] * result.elems[10]; 71 | 72 | temp[4] = -result.elems[4] * result.elems[10] * result.elems[15] + 73 | result.elems[4] * result.elems[11] * result.elems[14] + 74 | result.elems[8] * result.elems[6] * result.elems[15] - 75 | result.elems[8] * result.elems[7] * result.elems[14] - 76 | result.elems[12] * result.elems[6] * result.elems[11] + 77 | result.elems[12] * result.elems[7] * result.elems[10]; 78 | 79 | temp[8] = result.elems[4] * result.elems[9] * result.elems[15] - 80 | result.elems[4] * result.elems[11] * result.elems[13] - 81 | result.elems[8] * result.elems[5] * result.elems[15] + 82 | result.elems[8] * result.elems[7] * result.elems[13] + 83 | result.elems[12] * result.elems[5] * result.elems[11] - 84 | result.elems[12] * result.elems[7] * result.elems[9]; 85 | 86 | temp[12] = -result.elems[4] * result.elems[9] * result.elems[14] + 87 | result.elems[4] * result.elems[10] * result.elems[13] + 88 | result.elems[8] * result.elems[5] * result.elems[14] - 89 | result.elems[8] * result.elems[6] * result.elems[13] - 90 | result.elems[12] * result.elems[5] * result.elems[10] + 91 | result.elems[12] * result.elems[6] * result.elems[9]; 92 | 93 | temp[1] = -result.elems[1] * result.elems[10] * result.elems[15] + 94 | result.elems[1] * result.elems[11] * result.elems[14] + 95 | result.elems[9] * result.elems[2] * result.elems[15] - 96 | result.elems[9] * result.elems[3] * result.elems[14] - 97 | result.elems[13] * result.elems[2] * result.elems[11] + 98 | result.elems[13] * result.elems[3] * result.elems[10]; 99 | 100 | temp[5] = result.elems[0] * result.elems[10] * result.elems[15] - 101 | result.elems[0] * result.elems[11] * result.elems[14] - 102 | result.elems[8] * result.elems[2] * result.elems[15] + 103 | result.elems[8] * result.elems[3] * result.elems[14] + 104 | result.elems[12] * result.elems[2] * result.elems[11] - 105 | result.elems[12] * result.elems[3] * result.elems[10]; 106 | 107 | temp[9] = -result.elems[0] * result.elems[9] * result.elems[15] + 108 | result.elems[0] * result.elems[11] * result.elems[13] + 109 | result.elems[8] * result.elems[1] * result.elems[15] - 110 | result.elems[8] * result.elems[3] * result.elems[13] - 111 | result.elems[12] * result.elems[1] * result.elems[11] + 112 | result.elems[12] * result.elems[3] * result.elems[9]; 113 | 114 | temp[13] = result.elems[0] * result.elems[9] * result.elems[14] - 115 | result.elems[0] * result.elems[10] * result.elems[13] - 116 | result.elems[8] * result.elems[1] * result.elems[14] + 117 | result.elems[8] * result.elems[2] * result.elems[13] + 118 | result.elems[12] * result.elems[1] * result.elems[10] - 119 | result.elems[12] * result.elems[2] * result.elems[9]; 120 | 121 | temp[2] = result.elems[1] * result.elems[6] * result.elems[15] - 122 | result.elems[1] * result.elems[7] * result.elems[14] - 123 | result.elems[5] * result.elems[2] * result.elems[15] + 124 | result.elems[5] * result.elems[3] * result.elems[14] + 125 | result.elems[13] * result.elems[2] * result.elems[7] - 126 | result.elems[13] * result.elems[3] * result.elems[6]; 127 | 128 | temp[6] = -result.elems[0] * result.elems[6] * result.elems[15] + 129 | result.elems[0] * result.elems[7] * result.elems[14] + 130 | result.elems[4] * result.elems[2] * result.elems[15] - 131 | result.elems[4] * result.elems[3] * result.elems[14] - 132 | result.elems[12] * result.elems[2] * result.elems[7] + 133 | result.elems[12] * result.elems[3] * result.elems[6]; 134 | 135 | temp[10] = result.elems[0] * result.elems[5] * result.elems[15] - 136 | result.elems[0] * result.elems[7] * result.elems[13] - 137 | result.elems[4] * result.elems[1] * result.elems[15] + 138 | result.elems[4] * result.elems[3] * result.elems[13] + 139 | result.elems[12] * result.elems[1] * result.elems[7] - 140 | result.elems[12] * result.elems[3] * result.elems[5]; 141 | 142 | temp[14] = -result.elems[0] * result.elems[5] * result.elems[14] + 143 | result.elems[0] * result.elems[6] * result.elems[13] + 144 | result.elems[4] * result.elems[1] * result.elems[14] - 145 | result.elems[4] * result.elems[2] * result.elems[13] - 146 | result.elems[12] * result.elems[1] * result.elems[6] + 147 | result.elems[12] * result.elems[2] * result.elems[5]; 148 | 149 | temp[3] = -result.elems[1] * result.elems[6] * result.elems[11] + 150 | result.elems[1] * result.elems[7] * result.elems[10] + 151 | result.elems[5] * result.elems[2] * result.elems[11] - 152 | result.elems[5] * result.elems[3] * result.elems[10] - 153 | result.elems[9] * result.elems[2] * result.elems[7] + 154 | result.elems[9] * result.elems[3] * result.elems[6]; 155 | 156 | temp[7] = result.elems[0] * result.elems[6] * result.elems[11] - 157 | result.elems[0] * result.elems[7] * result.elems[10] - 158 | result.elems[4] * result.elems[2] * result.elems[11] + 159 | result.elems[4] * result.elems[3] * result.elems[10] + 160 | result.elems[8] * result.elems[2] * result.elems[7] - 161 | result.elems[8] * result.elems[3] * result.elems[6]; 162 | 163 | temp[11] = -result.elems[0] * result.elems[5] * result.elems[11] + 164 | result.elems[0] * result.elems[7] * result.elems[9] + 165 | result.elems[4] * result.elems[1] * result.elems[11] - 166 | result.elems[4] * result.elems[3] * result.elems[9] - 167 | result.elems[8] * result.elems[1] * result.elems[7] + 168 | result.elems[8] * result.elems[3] * result.elems[5]; 169 | 170 | temp[15] = result.elems[0] * result.elems[5] * result.elems[10] - 171 | result.elems[0] * result.elems[6] * result.elems[9] - 172 | result.elems[4] * result.elems[1] * result.elems[10] + 173 | result.elems[4] * result.elems[2] * result.elems[9] + 174 | result.elems[8] * result.elems[1] * result.elems[6] - 175 | result.elems[8] * result.elems[2] * result.elems[5]; 176 | 177 | f32 determinant = result.elems[0] * temp[0] + result.elems[1] * temp[4] + result.elems[2] * temp[8] + result.elems[3] * temp[12]; 178 | determinant = 1.0f / determinant; 179 | 180 | for (u8 i = 0; i < 4 * 4; i++) { 181 | result.elems[i] = temp[i] * determinant; 182 | } 183 | 184 | return result; 185 | } 186 | 187 | void ch::Matrix4::operator*=(const Matrix4& right) { 188 | *this = *this * right; 189 | } 190 | 191 | ch::Stream& ch::operator<<(ch::Stream &stream, Vector2 vec) { 192 | stream << '{' << vec.x << ", " << vec.y << "}\n"; 193 | return stream; 194 | } 195 | 196 | ch::Stream& ch::operator<<(Stream& stream, const Color& color) { 197 | stream << color.r << (char)' ' << color.g << (char)' ' << color.b << (char)' ' << color.a; 198 | return stream; 199 | } 200 | 201 | ch::Matrix4 ch::identity() { 202 | ch::Matrix4 result = {}; 203 | result[0 + 0 * 4] = 1.0f; 204 | result[1 + 1 * 4] = 1.0f; 205 | result[2 + 2 * 4] = 1.0f; 206 | result[3 + 3 * 4] = 1.0f; 207 | return result; 208 | } 209 | 210 | ch::Matrix4 ch::ortho(f32 left, f32 right, f32 top, f32 bottom, f32 far, f32 near) { 211 | Matrix4 result = ch::identity(); 212 | 213 | result.elems[0 + 0 * 4] = 2.f / (right - left); 214 | result.elems[1 + 1 * 4] = 2.f / (top - bottom); 215 | result.elems[2 + 2 * 4] = -2.f / (far - near); 216 | 217 | result.elems[0 + 3 * 4] = -((right + left) / (right - left)); 218 | result.elems[1 + 3 * 4] = -((top + bottom) / (top - bottom)); 219 | result.elems[2 + 3 * 4] = -((far + near) / (far - near)); 220 | 221 | return result; 222 | } 223 | 224 | ch::Matrix4 ch::ortho(f32 size, f32 aspect_ratio, f32 far, f32 near) { 225 | const float right = size * aspect_ratio; 226 | const float left = -right; 227 | 228 | const float top = size; 229 | const float bottom = -top; 230 | 231 | return ch::ortho(left, right, top, bottom, far, near); 232 | } 233 | 234 | ch::Matrix4 ch::perspective(f32 fov, f32 aspect_ratio, f32 far, f32 near) { 235 | ch::Matrix4 result = ch::identity(); 236 | const float q = 1.f / ch::tan(fov * 0.5f * ch::to_rad); 237 | const float a = q / aspect_ratio; 238 | const float b = (near + far) / (near - far); 239 | const float c = (2.f * near * far) / (near - far); 240 | 241 | result[0 + 0 * 4] = a; 242 | result[1 + 1 * 4] = q; 243 | result[2 + 2 * 4] = b; 244 | result[3 + 2 * 4] = -1; 245 | result[2 + 3 * 4] = c; 246 | 247 | return result; 248 | } 249 | 250 | ch::Matrix4 ch::translate(const Vector3& pos) { 251 | ch::Matrix4 result = ch::identity(); 252 | result[0 + 3 * 4] = pos.x; 253 | result[1 + 3 * 4] = pos.y; 254 | result[2 + 3 * 4] = pos.z; 255 | return result; 256 | } 257 | 258 | ch::Matrix4 ch::rotate(f32 angle, const ch::Vector3& axis) { 259 | ch::Matrix4 result = ch::identity(); 260 | const f32 r = angle * ch::to_rad; 261 | const f32 c = ch::cos(r); 262 | const f32 s = ch::sin(r); 263 | const f32 omc = 1 - c; 264 | 265 | const f32 x = axis.x; 266 | const f32 y = axis.y; 267 | const f32 z = axis.z; 268 | result.elems[0 + 0 * 4] = x * omc + c; 269 | result.elems[1 + 0 * 4] = y * x * omc + z * s; 270 | result.elems[2 + 0 * 4] = x * z * omc - y * s; 271 | result.elems[0 + 1 * 4] = x * y * omc - z * s; 272 | result.elems[1 + 1 * 4] = y * omc + c; 273 | result.elems[2 + 1 * 4] = y * z * omc + x * s; 274 | result.elems[0 + 2 * 4] = x * z * omc + y * s; 275 | result.elems[1 + 2 * 4] = y * z * omc - x * s; 276 | result.elems[2 + 2 * 4] = z * omc + c; 277 | 278 | return result; 279 | } 280 | 281 | ch::Matrix4 ch::scale(const Vector3& scale) { 282 | ch::Matrix4 result = ch::identity(); 283 | result[0 + 0 * 4] = scale.x; 284 | result[1 + 1 * 4] = scale.y; 285 | result[2 + 2 * 4] = scale.z; 286 | return result; 287 | } 288 | 289 | u64 hash(ch::Vector2 v) { 290 | return ch::fnv1_hash(&v, sizeof(ch::Vector2)); 291 | } 292 | -------------------------------------------------------------------------------- /opengl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "window.h" 4 | #include "math.h" 5 | 6 | #if CH_PLATFORM_WINDOWS 7 | #include "win32/opengl_win32.h" 8 | #endif 9 | 10 | #include "thirdparty/glext.h" 11 | 12 | #define GL_BINDINGS(macro) \ 13 | macro(PFNGLBINDSAMPLERPROC,glBindSampler) \ 14 | macro(PFNGLDELETESAMPLERSPROC,glDeleteSamplers) \ 15 | macro(PFNGLGENSAMPLERSPROC,glGenSamplers) \ 16 | macro(PFNGLSAMPLERPARAMETERIPROC,glSamplerParameteri) \ 17 | macro(PFNGLCLEARBUFFERFVPROC,glClearBufferfv) \ 18 | macro(PFNGLCLEARBUFFERIVPROC,glClearBufferiv) \ 19 | macro(PFNGLCLEARBUFFERUIVPROC,glClearBufferuiv) \ 20 | macro(PFNGLCLEARBUFFERFIPROC,glClearBufferfi) \ 21 | macro(PFNGLCOLORMASKIPROC,glColorMaski) \ 22 | macro(PFNGLDISABLEIPROC,glDisablei) \ 23 | macro(PFNGLENABLEIPROC,glEnablei) \ 24 | macro(PFNGLGETBOOLEANI_VPROC,glGetBooleani_v) \ 25 | macro(PFNGLGETINTEGERI_VPROC,glGetIntegeri_v) \ 26 | macro(PFNGLISENABLEDIPROC,glIsEnabledi) \ 27 | macro(PFNGLBLENDCOLORPROC,glBlendColor) \ 28 | macro(PFNGLBLENDEQUATIONPROC,glBlendEquation) \ 29 | macro(PFNGLDRAWRANGEELEMENTSPROC,glDrawRangeElements) \ 30 | macro(PFNGLTEXIMAGE3DPROC,glTexImage3D) \ 31 | macro(PFNGLTEXSUBIMAGE3DPROC,glTexSubImage3D) \ 32 | macro(PFNGLCOPYTEXSUBIMAGE3DPROC,glCopyTexSubImage3D) \ 33 | macro(PFNGLACTIVETEXTUREPROC,glActiveTexture) \ 34 | macro(PFNGLSAMPLECOVERAGEPROC,glSampleCoverage) \ 35 | macro(PFNGLCOMPRESSEDTEXIMAGE3DPROC,glCompressedTexImage3D) \ 36 | macro(PFNGLCOMPRESSEDTEXIMAGE2DPROC,glCompressedTexImage2D) \ 37 | macro(PFNGLCOMPRESSEDTEXIMAGE1DPROC,glCompressedTexImage1D) \ 38 | macro(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC,glCompressedTexSubImage3D) \ 39 | macro(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC,glCompressedTexSubImage2D) \ 40 | macro(PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC,glCompressedTexSubImage1D) \ 41 | macro(PFNGLGETCOMPRESSEDTEXIMAGEPROC,glGetCompressedTexImage) \ 42 | macro(PFNGLBLENDFUNCSEPARATEPROC,glBlendFuncSeparate) \ 43 | macro(PFNGLMULTIDRAWARRAYSPROC,glMultiDrawArrays) \ 44 | macro(PFNGLMULTIDRAWELEMENTSPROC,glMultiDrawElements) \ 45 | macro(PFNGLPOINTPARAMETERFPROC,glPointParameterf) \ 46 | macro(PFNGLPOINTPARAMETERFVPROC,glPointParameterfv) \ 47 | macro(PFNGLPOINTPARAMETERIPROC,glPointParameteri) \ 48 | macro(PFNGLPOINTPARAMETERIVPROC,glPointParameteriv) \ 49 | macro(PFNGLGENQUERIESPROC,glGenQueries) \ 50 | macro(PFNGLDELETEQUERIESPROC,glDeleteQueries) \ 51 | macro(PFNGLISQUERYPROC,glIsQuery) \ 52 | macro(PFNGLBEGINQUERYPROC,glBeginQuery) \ 53 | macro(PFNGLENDQUERYPROC,glEndQuery) \ 54 | macro(PFNGLGETQUERYIVPROC,glGetQueryiv) \ 55 | macro(PFNGLGETQUERYOBJECTIVPROC,glGetQueryObjectiv) \ 56 | macro(PFNGLGETQUERYOBJECTUIVPROC,glGetQueryObjectuiv) \ 57 | macro(PFNGLBINDBUFFERPROC,glBindBuffer) \ 58 | macro(PFNGLBINDBUFFERBASEPROC,glBindBufferBase) \ 59 | macro(PFNGLDELETEBUFFERSPROC,glDeleteBuffers) \ 60 | macro(PFNGLGENBUFFERSPROC,glGenBuffers) \ 61 | macro(PFNGLISBUFFERPROC,glIsBuffer) \ 62 | macro(PFNGLBUFFERDATAPROC,glBufferData) \ 63 | macro(PFNGLBUFFERSUBDATAPROC,glBufferSubData) \ 64 | macro(PFNGLGETBUFFERSUBDATAPROC,glGetBufferSubData) \ 65 | macro(PFNGLMAPBUFFERPROC,glMapBuffer) \ 66 | macro(PFNGLUNMAPBUFFERPROC,glUnmapBuffer) \ 67 | macro(PFNGLGETBUFFERPARAMETERIVPROC,glGetBufferParameteriv) \ 68 | macro(PFNGLGETBUFFERPOINTERVPROC,glGetBufferPointerv) \ 69 | macro(PFNGLBLENDEQUATIONSEPARATEPROC,glBlendEquationSeparate) \ 70 | macro(PFNGLDRAWBUFFERSPROC,glDrawBuffers) \ 71 | macro(PFNGLSTENCILOPSEPARATEPROC,glStencilOpSeparate) \ 72 | macro(PFNGLSTENCILFUNCSEPARATEPROC,glStencilFuncSeparate) \ 73 | macro(PFNGLSTENCILMASKSEPARATEPROC,glStencilMaskSeparate) \ 74 | macro(PFNGLATTACHSHADERPROC,glAttachShader) \ 75 | macro(PFNGLBINDATTRIBLOCATIONPROC,glBindAttribLocation) \ 76 | macro(PFNGLBINDFRAGDATALOCATIONPROC,glBindFragDataLocation) \ 77 | macro(PFNGLCOMPILESHADERPROC,glCompileShader) \ 78 | macro(PFNGLCREATEPROGRAMPROC,glCreateProgram) \ 79 | macro(PFNGLCREATESHADERPROC,glCreateShader) \ 80 | macro(PFNGLDELETEPROGRAMPROC,glDeleteProgram) \ 81 | macro(PFNGLDELETESHADERPROC,glDeleteShader) \ 82 | macro(PFNGLDETACHSHADERPROC,glDetachShader) \ 83 | macro(PFNGLDISABLEVERTEXATTRIBARRAYPROC,glDisableVertexAttribArray) \ 84 | macro(PFNGLENABLEVERTEXATTRIBARRAYPROC,glEnableVertexAttribArray) \ 85 | macro(PFNGLGETACTIVEATTRIBPROC,glGetActiveAttrib) \ 86 | macro(PFNGLGETACTIVEUNIFORMPROC,glGetActiveUniform) \ 87 | macro(PFNGLGETATTACHEDSHADERSPROC,glGetAttachedShaders) \ 88 | macro(PFNGLGETATTRIBLOCATIONPROC,glGetAttribLocation) \ 89 | macro(PFNGLGETPROGRAMIVPROC,glGetProgramiv) \ 90 | macro(PFNGLGETPROGRAMINFOLOGPROC,glGetProgramInfoLog) \ 91 | macro(PFNGLGETSHADERIVPROC,glGetShaderiv) \ 92 | macro(PFNGLGETSHADERINFOLOGPROC,glGetShaderInfoLog) \ 93 | macro(PFNGLGETSHADERSOURCEPROC,glGetShaderSource) \ 94 | macro(PFNGLGETUNIFORMLOCATIONPROC,glGetUniformLocation) \ 95 | macro(PFNGLGETUNIFORMBLOCKINDEXPROC,glGetUniformBlockIndex) \ 96 | macro(PFNGLGETUNIFORMFVPROC,glGetUniformfv) \ 97 | macro(PFNGLGETUNIFORMIVPROC,glGetUniformiv) \ 98 | macro(PFNGLGETVERTEXATTRIBDVPROC,glGetVertexAttribdv) \ 99 | macro(PFNGLGETVERTEXATTRIBFVPROC,glGetVertexAttribfv) \ 100 | macro(PFNGLGETVERTEXATTRIBIVPROC,glGetVertexAttribiv) \ 101 | macro(PFNGLGETVERTEXATTRIBPOINTERVPROC,glGetVertexAttribPointerv) \ 102 | macro(PFNGLISPROGRAMPROC,glIsProgram) \ 103 | macro(PFNGLISSHADERPROC,glIsShader) \ 104 | macro(PFNGLLINKPROGRAMPROC,glLinkProgram) \ 105 | macro(PFNGLSHADERSOURCEPROC,glShaderSource) \ 106 | macro(PFNGLUSEPROGRAMPROC,glUseProgram) \ 107 | macro(PFNGLUNIFORM1FPROC,glUniform1f) \ 108 | macro(PFNGLUNIFORM2FPROC,glUniform2f) \ 109 | macro(PFNGLUNIFORM3FPROC,glUniform3f) \ 110 | macro(PFNGLUNIFORM4FPROC,glUniform4f) \ 111 | macro(PFNGLUNIFORM1IPROC,glUniform1i) \ 112 | macro(PFNGLUNIFORM2IPROC,glUniform2i) \ 113 | macro(PFNGLUNIFORM3IPROC,glUniform3i) \ 114 | macro(PFNGLUNIFORM4IPROC,glUniform4i) \ 115 | macro(PFNGLUNIFORM1FVPROC,glUniform1fv) \ 116 | macro(PFNGLUNIFORM2FVPROC,glUniform2fv) \ 117 | macro(PFNGLUNIFORM3FVPROC,glUniform3fv) \ 118 | macro(PFNGLUNIFORM4FVPROC,glUniform4fv) \ 119 | macro(PFNGLUNIFORM1IVPROC,glUniform1iv) \ 120 | macro(PFNGLUNIFORM2IVPROC,glUniform2iv) \ 121 | macro(PFNGLUNIFORM3IVPROC,glUniform3iv) \ 122 | macro(PFNGLUNIFORM4IVPROC,glUniform4iv) \ 123 | macro(PFNGLUNIFORM1UIVPROC,glUniform1uiv) \ 124 | macro(PFNGLUNIFORM2UIVPROC,glUniform2uiv) \ 125 | macro(PFNGLUNIFORM3UIVPROC,glUniform3uiv) \ 126 | macro(PFNGLUNIFORM4UIVPROC,glUniform4uiv) \ 127 | macro(PFNGLUNIFORMBLOCKBINDINGPROC,glUniformBlockBinding) \ 128 | macro(PFNGLUNIFORMMATRIX2FVPROC,glUniformMatrix2fv) \ 129 | macro(PFNGLUNIFORMMATRIX3FVPROC,glUniformMatrix3fv) \ 130 | macro(PFNGLUNIFORMMATRIX4FVPROC,glUniformMatrix4fv) \ 131 | macro(PFNGLVALIDATEPROGRAMPROC,glValidateProgram) \ 132 | macro(PFNGLVERTEXATTRIB1DPROC,glVertexAttrib1d) \ 133 | macro(PFNGLVERTEXATTRIB1DVPROC,glVertexAttrib1dv) \ 134 | macro(PFNGLVERTEXATTRIB1FPROC,glVertexAttrib1f) \ 135 | macro(PFNGLVERTEXATTRIB1FVPROC,glVertexAttrib1fv) \ 136 | macro(PFNGLVERTEXATTRIB1SPROC,glVertexAttrib1s) \ 137 | macro(PFNGLVERTEXATTRIB1SVPROC,glVertexAttrib1sv) \ 138 | macro(PFNGLVERTEXATTRIB2DPROC,glVertexAttrib2d) \ 139 | macro(PFNGLVERTEXATTRIB2DVPROC,glVertexAttrib2dv) \ 140 | macro(PFNGLVERTEXATTRIB2FPROC,glVertexAttrib2f) \ 141 | macro(PFNGLVERTEXATTRIB2FVPROC,glVertexAttrib2fv) \ 142 | macro(PFNGLVERTEXATTRIB2SPROC,glVertexAttrib2s) \ 143 | macro(PFNGLVERTEXATTRIB2SVPROC,glVertexAttrib2sv) \ 144 | macro(PFNGLVERTEXATTRIB3DPROC,glVertexAttrib3d) \ 145 | macro(PFNGLVERTEXATTRIB3DVPROC,glVertexAttrib3dv) \ 146 | macro(PFNGLVERTEXATTRIB3FPROC,glVertexAttrib3f) \ 147 | macro(PFNGLVERTEXATTRIB3FVPROC,glVertexAttrib3fv) \ 148 | macro(PFNGLVERTEXATTRIB3SPROC,glVertexAttrib3s) \ 149 | macro(PFNGLVERTEXATTRIB3SVPROC,glVertexAttrib3sv) \ 150 | macro(PFNGLVERTEXATTRIB4NBVPROC,glVertexAttrib4Nbv) \ 151 | macro(PFNGLVERTEXATTRIB4NIVPROC,glVertexAttrib4Niv) \ 152 | macro(PFNGLVERTEXATTRIB4NSVPROC,glVertexAttrib4Nsv) \ 153 | macro(PFNGLVERTEXATTRIB4NUBPROC,glVertexAttrib4Nub) \ 154 | macro(PFNGLVERTEXATTRIB4NUBVPROC,glVertexAttrib4Nubv) \ 155 | macro(PFNGLVERTEXATTRIB4NUIVPROC,glVertexAttrib4Nuiv) \ 156 | macro(PFNGLVERTEXATTRIB4NUSVPROC,glVertexAttrib4Nusv) \ 157 | macro(PFNGLVERTEXATTRIB4BVPROC,glVertexAttrib4bv) \ 158 | macro(PFNGLVERTEXATTRIB4DPROC,glVertexAttrib4d) \ 159 | macro(PFNGLVERTEXATTRIB4DVPROC,glVertexAttrib4dv) \ 160 | macro(PFNGLVERTEXATTRIB4FPROC,glVertexAttrib4f) \ 161 | macro(PFNGLVERTEXATTRIB4FVPROC,glVertexAttrib4fv) \ 162 | macro(PFNGLVERTEXATTRIB4IVPROC,glVertexAttrib4iv) \ 163 | macro(PFNGLVERTEXATTRIB4SPROC,glVertexAttrib4s) \ 164 | macro(PFNGLVERTEXATTRIB4SVPROC,glVertexAttrib4sv) \ 165 | macro(PFNGLVERTEXATTRIB4UBVPROC,glVertexAttrib4ubv) \ 166 | macro(PFNGLVERTEXATTRIB4UIVPROC,glVertexAttrib4uiv) \ 167 | macro(PFNGLVERTEXATTRIB4USVPROC,glVertexAttrib4usv) \ 168 | macro(PFNGLVERTEXATTRIBI4IVPROC,glVertexAttribI4iv) \ 169 | macro(PFNGLVERTEXATTRIBI4UIVPROC,glVertexAttribI4uiv) \ 170 | macro(PFNGLVERTEXATTRIBI4SVPROC,glVertexAttribI4sv) \ 171 | macro(PFNGLVERTEXATTRIBI4USVPROC,glVertexAttribI4usv) \ 172 | macro(PFNGLVERTEXATTRIBI4BVPROC,glVertexAttribI4bv) \ 173 | macro(PFNGLVERTEXATTRIBI4UBVPROC,glVertexAttribI4ubv) \ 174 | macro(PFNGLVERTEXATTRIBPOINTERPROC,glVertexAttribPointer) \ 175 | macro(PFNGLVERTEXATTRIBIPOINTERPROC,glVertexAttribIPointer) \ 176 | macro(PFNGLUNIFORMMATRIX2X3FVPROC,glUniformMatrix2x3fv) \ 177 | macro(PFNGLUNIFORMMATRIX3X2FVPROC,glUniformMatrix3x2fv) \ 178 | macro(PFNGLUNIFORMMATRIX2X4FVPROC,glUniformMatrix2x4fv) \ 179 | macro(PFNGLUNIFORMMATRIX4X2FVPROC,glUniformMatrix4x2fv) \ 180 | macro(PFNGLUNIFORMMATRIX3X4FVPROC,glUniformMatrix3x4fv) \ 181 | macro(PFNGLUNIFORMMATRIX4X3FVPROC,glUniformMatrix4x3fv) \ 182 | macro(PFNGLISRENDERBUFFERPROC,glIsRenderbuffer) \ 183 | macro(PFNGLBINDRENDERBUFFERPROC,glBindRenderbuffer) \ 184 | macro(PFNGLDELETERENDERBUFFERSPROC,glDeleteRenderbuffers) \ 185 | macro(PFNGLGENRENDERBUFFERSPROC,glGenRenderbuffers) \ 186 | macro(PFNGLRENDERBUFFERSTORAGEPROC,glRenderbufferStorage) \ 187 | macro(PFNGLGETRENDERBUFFERPARAMETERIVPROC,glGetRenderbufferParameteriv) \ 188 | macro(PFNGLISFRAMEBUFFERPROC,glIsFramebuffer) \ 189 | macro(PFNGLBINDFRAMEBUFFERPROC,glBindFramebuffer) \ 190 | macro(PFNGLDELETEFRAMEBUFFERSPROC,glDeleteFramebuffers) \ 191 | macro(PFNGLGENFRAMEBUFFERSPROC,glGenFramebuffers) \ 192 | macro(PFNGLCHECKFRAMEBUFFERSTATUSPROC,glCheckFramebufferStatus) \ 193 | macro(PFNGLFRAMEBUFFERTEXTURE1DPROC,glFramebufferTexture1D) \ 194 | macro(PFNGLFRAMEBUFFERTEXTURE2DPROC,glFramebufferTexture2D) \ 195 | macro(PFNGLFRAMEBUFFERTEXTURE3DPROC,glFramebufferTexture3D) \ 196 | macro(PFNGLFRAMEBUFFERTEXTUREPROC,glFramebufferTexture) \ 197 | macro(PFNGLFRAMEBUFFERRENDERBUFFERPROC,glFramebufferRenderbuffer) \ 198 | macro(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC,glGetFramebufferAttachmentParameteriv) \ 199 | macro(PFNGLGENERATEMIPMAPPROC,glGenerateMipmap) \ 200 | macro(PFNGLBLITFRAMEBUFFERPROC,glBlitFramebuffer) \ 201 | macro(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC,glRenderbufferStorageMultisample) \ 202 | macro(PFNGLFRAMEBUFFERTEXTURELAYERPROC,glFramebufferTextureLayer) \ 203 | macro(PFNGLMAPBUFFERRANGEPROC,glMapBufferRange) \ 204 | macro(PFNGLFLUSHMAPPEDBUFFERRANGEPROC,glFlushMappedBufferRange) \ 205 | macro(PFNGLVERTEXATTRIBDIVISORPROC,glVertexAttribDivisor) \ 206 | macro(PFNGLDRAWARRAYSINSTANCEDPROC,glDrawArraysInstanced) \ 207 | macro(PFNGLDRAWELEMENTSINSTANCEDPROC,glDrawElementsInstanced) \ 208 | macro(PFNGLGETSTRINGIPROC,glGetStringi) \ 209 | macro(PFNGLGENVERTEXARRAYSPROC,glGenVertexArrays) \ 210 | macro(PFNGLDELETEVERTEXARRAYSPROC,glDeleteVertexArrays) \ 211 | macro(PFNGLBINDVERTEXARRAYPROC,glBindVertexArray) \ 212 | macro(PFNGLCOPYBUFFERSUBDATAPROC,glCopyBufferSubData) \ 213 | macro(PFNGLTEXBUFFERPROC,glTexBuffer) \ 214 | macro(PFNGLTEXIMAGE2DMULTISAMPLEPROC,glTexImage2DMultisample) \ 215 | macro(PFNGLQUERYCOUNTERPROC, glQueryCounter)\ 216 | macro(PFNGLISSYNCPROC, glIsSync)\ 217 | macro(PFNGLDELETESYNCPROC, glDeleteSync)\ 218 | macro(PFNGLGETQUERYOBJECTUI64VPROC, glGetQueryObjectui64v)\ 219 | macro(PFNGLFENCESYNCPROC, glFenceSync)\ 220 | macro(PFNGLGETSYNCIVPROC, glGetSynciv)\ 221 | macro(PFNGLCLIENTWAITSYNCPROC, glClientWaitSync)\ 222 | macro(PFNGLBINDBUFFERRANGEPROC, glBindBufferRange)\ 223 | macro(PFNGLDEBUGMESSAGECALLBACKPROC, glDebugMessageCallback) 224 | 225 | #define DECLARE_GL_FUNCTIONS(type, func) extern type func; 226 | GL_BINDINGS(DECLARE_GL_FUNCTIONS); 227 | #undef DECLARE_GL_FUNCTIONS 228 | 229 | namespace ch { 230 | bool load_gl(); 231 | 232 | bool is_gl_loaded(); 233 | 234 | bool swap_buffers(OS_Window_Handle window_handle); 235 | bool create_gl_window(const char* title, u32 width, u32 height, u32 style, ch::Window* out_window); 236 | bool make_current(OS_Window_Handle window_handle); 237 | } 238 | 239 | CH_FORCEINLINE void glClearColor(const ch::Color& color) { 240 | glClearColor(color.r, color.g, color.b, color.a); 241 | } -------------------------------------------------------------------------------- /math.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "memory.h" 4 | // @TODO(CHall): Finish math lib 5 | // Scalar Math 6 | // Vector4 7 | // Quaternion 8 | // Plane 9 | // Matrix4x4 10 | 11 | namespace ch { 12 | 13 | struct Stream; 14 | 15 | f32 sqrt(f32 s); 16 | 17 | f32 cos(f32 s); 18 | 19 | f32 sin(f32 s); 20 | f32 asin(f32 s); 21 | 22 | f32 tan(f32 s); 23 | f32 atan(f32 s); 24 | f32 atan2(f32 x, f32 y); 25 | 26 | const f32 pi = 3.1415f; 27 | const f32 tau = (pi * 2.f); 28 | 29 | const f32 to_rad = pi / 180.f; 30 | const f32 to_deg = 180.f / pi; 31 | 32 | const f32 small_number = 1.e-8f; 33 | const f32 kinda_small_number = 1.e-4f; 34 | const f32 big_number = 3.4e+38f; 35 | 36 | template 37 | T clamp(T value, T min, T max) { 38 | if (value < min) return min; 39 | if (value > max) return max; 40 | return value; 41 | } 42 | 43 | template 44 | T min(T a, T b) { 45 | if (a < b) return a; 46 | return b; 47 | } 48 | 49 | template 50 | T max(T a, T b) { 51 | if (a > b) return a; 52 | return b; 53 | } 54 | 55 | template 56 | T abs(const T& t) { 57 | if (t < 0) return -t; 58 | return t; 59 | } 60 | 61 | template 62 | T floor(const T& t) { 63 | return t; 64 | } 65 | 66 | template<> 67 | CH_FORCEINLINE f32 ch::floor(const f32& t) { 68 | return (f32)((s32)t); 69 | } 70 | 71 | template 72 | T round(const T& t) { 73 | return t; 74 | } 75 | 76 | template<> 77 | CH_FORCEINLINE f32 ch::round(const f32& t) { 78 | if (t > 0.f) { 79 | return ch::floor(t + 0.5f); 80 | } 81 | 82 | return ch::floor(t - 0.5f); 83 | } 84 | 85 | template 86 | T ceil(const T& t) { 87 | return t; 88 | } 89 | 90 | template<> 91 | CH_FORCEINLINE f32 ch::ceil(const f32& t) { 92 | if (t > 0.f) { 93 | return ch::round(t + 0.5f); 94 | } 95 | 96 | return ch::round(t - 0.5f); 97 | } 98 | 99 | 100 | template 101 | bool in_range(T value, T min, T max) { 102 | return value == ch::clamp(value, min, max); 103 | } 104 | 105 | // @TODO(Chall): not finished 106 | template 107 | CH_FORCEINLINE u32 get_num_digits(T t) { 108 | u32 result = 1; 109 | while (t >= (T)10) { 110 | result += 1; 111 | t /= (T)10; 112 | } 113 | 114 | return result; 115 | } 116 | 117 | CH_FORCEINLINE f32 interp_to(f32 current, f32 target, f32 delta_time, f32 speed) { 118 | if (speed <= 0.f) return target; 119 | 120 | const f32 distance = target - current; 121 | if (distance * distance < ch::small_number) { 122 | return target; 123 | } 124 | 125 | const f32 delta_move = distance * ch::clamp(delta_time * speed, 0.f, 1.f); 126 | return current + delta_move; 127 | } 128 | 129 | struct Vector2 { 130 | union { 131 | struct { f32 x, y; }; 132 | struct { f32 u, v; }; 133 | struct { s32 ix, iy; }; 134 | struct { u32 ux, uy; }; 135 | f32 xy[2]; 136 | f32 uv[2]; 137 | }; 138 | 139 | Vector2() : x(0.f), y(0.f) {} 140 | Vector2(f32 xy) : x(xy), y(xy) {} 141 | Vector2(s32 ixy) : ix(ixy), iy(ixy) {} 142 | Vector2(f32 _x, f32 _y) : x(_x), y(_y) {} 143 | 144 | explicit operator bool() const { return x != 0.f || y != 0.f; } 145 | 146 | bool operator==(const Vector2& right) const { 147 | return x == right.x && y == right.y; 148 | } 149 | 150 | bool operator!=(const Vector2& right) const { 151 | return !(*this == right); 152 | } 153 | 154 | CH_FORCEINLINE Vector2 operator+(const Vector2& right) const { 155 | return Vector2(x + right.x, y + right.y); 156 | } 157 | 158 | CH_FORCEINLINE void operator+=(const Vector2& right) { 159 | *this = *this + right; 160 | } 161 | 162 | CH_FORCEINLINE Vector2 operator+(f32 s) const { 163 | return Vector2(x + s, y + s); 164 | } 165 | 166 | CH_FORCEINLINE void operator+=(f32 s) { 167 | *this = *this + s; 168 | } 169 | 170 | CH_FORCEINLINE Vector2 operator-(const Vector2& right) const { 171 | return Vector2(x - right.x, y - right.y); 172 | } 173 | 174 | CH_FORCEINLINE void operator-=(const Vector2& right) { 175 | *this = *this - right; 176 | } 177 | 178 | CH_FORCEINLINE Vector2 operator-(f32 s) const { 179 | return Vector2(x - s, y - s); 180 | } 181 | 182 | CH_FORCEINLINE void operator-=(f32 s) { 183 | *this = *this - s; 184 | } 185 | 186 | CH_FORCEINLINE Vector2 operator*(const Vector2& right) const { 187 | return Vector2(x * right.x, y * right.y); 188 | } 189 | 190 | CH_FORCEINLINE void operator*=(const Vector2& right) { 191 | *this = *this * right; 192 | } 193 | 194 | CH_FORCEINLINE Vector2 operator*(f32 s) const { 195 | return Vector2(x * s, y * s); 196 | } 197 | 198 | CH_FORCEINLINE void operator*=(f32 s) { 199 | *this = *this * s; 200 | } 201 | 202 | CH_FORCEINLINE Vector2 operator/(const Vector2& right) const { 203 | return Vector2(x / right.x, y / right.y); 204 | } 205 | 206 | CH_FORCEINLINE void operator/=(const Vector2& right) { 207 | *this = *this / right; 208 | } 209 | 210 | CH_FORCEINLINE Vector2 operator/(f32 s) const{ 211 | return Vector2(x / s, y / s); 212 | } 213 | 214 | CH_FORCEINLINE void operator/=(f32 s) { 215 | *this = *this / s; 216 | } 217 | 218 | CH_FORCEINLINE ch::Vector2 operator-() const { 219 | return ch::Vector2(-x, -y); 220 | } 221 | 222 | CH_FORCEINLINE f32 length_squared() const { 223 | return x * x + y * y; 224 | } 225 | 226 | CH_FORCEINLINE f32 length() const { 227 | return ch::sqrt(length_squared()); 228 | } 229 | 230 | CH_FORCEINLINE void normalize() { 231 | const f32 l = length(); 232 | if (l > 0.f) { 233 | *this /= l; 234 | } 235 | } 236 | 237 | CH_FORCEINLINE Vector2 get_normalized() const { 238 | Vector2 result = *this; 239 | result.normalize(); 240 | return result; 241 | } 242 | 243 | CH_FORCEINLINE bool is_normalized() const { 244 | return get_normalized().length() == 1.f; 245 | } 246 | 247 | CH_FORCEINLINE f32 dot(const Vector2& other) const { 248 | return x * other.x + y * other.y; 249 | } 250 | 251 | CH_FORCEINLINE f32 cross(ch::Vector2& other) const { 252 | return x * other.y - y * other.x; 253 | } 254 | }; 255 | 256 | template<> 257 | CH_FORCEINLINE ch::Vector2 ch::abs(const ch::Vector2& t) { 258 | ch::Vector2 result = t; 259 | if (t.x < 0.f) result.x = -t.x; 260 | if (t.y < 0.f) result.y = -t.y; 261 | return result; 262 | } 263 | 264 | template<> 265 | CH_FORCEINLINE ch::Vector2 ch::floor(const ch::Vector2& t) { 266 | ch::Vector2 result; 267 | result.x = ch::floor(t.x); 268 | result.y = ch::floor(t.y); 269 | return result; 270 | } 271 | 272 | template<> 273 | CH_FORCEINLINE ch::Vector2 ch::round(const ch::Vector2& t) { 274 | ch::Vector2 result; 275 | result.x = ch::round(t.x); 276 | result.y = ch::round(t.y); 277 | return result; 278 | } 279 | 280 | template<> 281 | CH_FORCEINLINE ch::Vector2 ch::ceil(const ch::Vector2& t) { 282 | ch::Vector2 result; 283 | result.x = ch::ceil(t.x); 284 | result.y = ch::ceil(t.y); 285 | return result; 286 | } 287 | 288 | Stream& operator<<(Stream& stream, ch::Vector2 vec); 289 | 290 | CH_FORCEINLINE ch::Vector2 from_angle(f32 angle) { 291 | return ch::Vector2(ch::sin(angle), ch::cos(angle)); 292 | } 293 | 294 | struct Vector3 { 295 | union { 296 | struct { f32 x, y, z; }; 297 | struct { f32 u, v, _; }; 298 | struct { f32 r, g, b; }; 299 | struct { s32 ix, iy, iz; }; 300 | struct { ch::Vector2 xy; f32 z; }; 301 | f32 xyz[3]; 302 | f32 uv[3]; 303 | }; 304 | 305 | Vector3() : x(0.f), y(0.f), z(0.f) {} 306 | Vector3(f32 xyz) : x(xyz), y(xyz), z(xyz) {} 307 | Vector3(s32 ixyz) : ix(ixyz), iy(ixyz), iz(ixyz) {} 308 | Vector3(f32 _x, f32 _y, f32 _z) : x(_x), y(_y), z(_z) {} 309 | Vector3(ch::Vector2 xy, f32 z = 0.f) : x(xy.x), y(xy.y), z(z) {} 310 | 311 | explicit operator bool() const { return x != 0.f || y != 0.f || z != 0.f; } 312 | 313 | bool operator==(const Vector3& right) const { 314 | return x == right.x && y == right.y && z == right.z; 315 | } 316 | 317 | bool operator!=(const Vector3& right) const { 318 | return !(*this == right); 319 | } 320 | 321 | CH_FORCEINLINE Vector3 operator+(const Vector3& right) const { 322 | return Vector3(x + right.x, y + right.y, z + right.z); 323 | } 324 | 325 | CH_FORCEINLINE void operator+=(const Vector3& right) { 326 | *this = *this + right; 327 | } 328 | 329 | CH_FORCEINLINE Vector3 operator+(f32 s) const { 330 | return Vector3(x + s, y + s, z + s); 331 | } 332 | 333 | CH_FORCEINLINE void operator+=(f32 s) { 334 | *this = *this + s; 335 | } 336 | 337 | CH_FORCEINLINE Vector3 operator-(const Vector3& right) const { 338 | return Vector3(x - right.x, y - right.y, z - right.z); 339 | } 340 | 341 | CH_FORCEINLINE void operator-=(const Vector3& right) { 342 | *this = *this - right; 343 | } 344 | 345 | CH_FORCEINLINE Vector3 operator-(f32 s) const { 346 | return Vector3(x - s, y - s, z - s); 347 | } 348 | 349 | CH_FORCEINLINE void operator-=(f32 s) { 350 | *this = *this - s; 351 | } 352 | 353 | CH_FORCEINLINE Vector3 operator*(const Vector3& right) const { 354 | return Vector3(x * right.x, y * right.y, z * right.z); 355 | } 356 | 357 | CH_FORCEINLINE void operator*=(const Vector3& right) { 358 | *this = *this * right; 359 | } 360 | 361 | CH_FORCEINLINE Vector3 operator*(f32 s) const { 362 | return Vector3(x * s, y * s, z * s); 363 | } 364 | 365 | CH_FORCEINLINE void operator*=(f32 s) { 366 | *this = *this * s; 367 | } 368 | 369 | CH_FORCEINLINE Vector3 operator/(const Vector3& right) const { 370 | return Vector3(x / right.x, y / right.y, z / right.z); 371 | } 372 | 373 | CH_FORCEINLINE void operator/=(const Vector3& right) { 374 | *this = *this / right; 375 | } 376 | 377 | CH_FORCEINLINE Vector3 operator/(f32 s) const { 378 | return Vector3(x / s, y / s, z / s); 379 | } 380 | 381 | CH_FORCEINLINE void operator/=(f32 s) { 382 | *this = *this / s; 383 | } 384 | 385 | CH_FORCEINLINE Vector3 operator-() const { 386 | return { -x, -y, -z }; 387 | } 388 | 389 | CH_FORCEINLINE f32 length_squared() const { 390 | return x * x + y * y + z * z; 391 | } 392 | 393 | CH_FORCEINLINE f32 length() const { 394 | return ch::sqrt(length_squared()); 395 | } 396 | 397 | CH_FORCEINLINE void normalize() { 398 | const f32 l = length(); 399 | if (l > 0.f) { 400 | *this /= l; 401 | } 402 | } 403 | 404 | CH_FORCEINLINE Vector3 get_normalized() const { 405 | Vector3 result = *this; 406 | result.normalize(); 407 | return result; 408 | } 409 | 410 | CH_FORCEINLINE bool is_normalized() const { 411 | return get_normalized().length() == 1.f; 412 | } 413 | 414 | CH_FORCEINLINE f32 dot(const Vector3& other) const { 415 | return x * other.x + y * other.y + z * other.z; 416 | } 417 | 418 | CH_FORCEINLINE Vector3 cross(const Vector3& other) const { 419 | Vector3 result; 420 | result.x = y * other.z - z * other.y; 421 | result.y = z * other.x - x * other.z; 422 | result.z = x * other.y - y * other.x; 423 | return result; 424 | } 425 | }; 426 | 427 | // @TODO(CHall): Finish 428 | struct Vector4 { 429 | union { 430 | struct { f32 x, y, z, w; }; 431 | struct { f32 r, g, b, a; }; 432 | struct { s32 ix, iy, iz, iw; }; 433 | struct { ch::Vector2 xy; ch::Vector2 zw; }; 434 | struct { ch::Vector3 xyz; f32 w; }; 435 | f32 xyzw[4]; 436 | f32 rgba[4]; 437 | }; 438 | 439 | Vector4() : x(0.f), y(0.f), z(0.f), w(0.f) {} 440 | Vector4(f32 xyzw) : x(xyzw), y(xyzw), z(xyzw), w(xyzw) {} 441 | Vector4(s32 ixyzw) : ix(ixyzw), iy(ixyzw), iz(ixyzw), iw(ixyzw) {} 442 | Vector4(f32 _x, f32 _y, f32 _z, f32 _w) : x(_x), y(_y), z(_z), w(_w) {} 443 | Vector4(ch::Vector2 xy, f32 _z = 0.f, f32 _w = 0.f) : x(xy.x), y(xy.y), z(_z), w(_w) {} 444 | }; 445 | 446 | struct Color { 447 | f32 r, g, b, a; 448 | 449 | Color() : r(0.f), g(0.f), b(0.f), a(0.f) {} 450 | Color(f32 _r, f32 _g, f32 _b, f32 _a) : r(_r), g(_g), b(_b), a(_a) {} 451 | Color(const ch::Vector3& rgb, f32 _a = 1.f) : r(rgb.r), g(rgb.g), b(rgb.b), a(_a) {} 452 | Color(const ch::Vector4& rgba) : r(rgba.r), g(rgba.g), b(rgba.b), a(rgba.a) {} 453 | CH_FORCEINLINE Color(s32 in_color) { 454 | const u8 red = (in_color & 0xFF000000) >> 24; 455 | const u8 green = (in_color & 0x00FF0000) >> 16; 456 | const u8 blue = (in_color & 0x0000FF00) >> 8; 457 | const u8 alpha = (in_color & 0x000000FF); 458 | 459 | r = (f32)red / (f32)0xFF; 460 | g = (f32)green / (f32)0xFF; 461 | b = (f32)blue / (f32)0xFF; 462 | a = (f32)alpha / (f32)0xFF; 463 | } 464 | 465 | CH_FORCEINLINE explicit operator s32() const { 466 | const u8 red = ((u8)r * 0xFF); 467 | const u8 green = ((u8)g * 0xFF); 468 | const u8 blue = ((u8)b * 0xFF); 469 | const u8 alpha = ((u8)a * 0xFF); 470 | 471 | // @NOTE(CHall): This feels bad 472 | s32 result = 0; 473 | result |= (s32)red << 24; 474 | result |= (s32)green << 16; 475 | result |= (s32)blue << 8; 476 | result |= (s32)alpha; 477 | 478 | return result; 479 | } 480 | 481 | CH_FORCEINLINE explicit operator ch::Vector3() const { 482 | return ch::Vector3(r, g, b); 483 | } 484 | 485 | CH_FORCEINLINE explicit operator ch::Vector4() const { 486 | return ch::Vector4(r, g, b, a); 487 | } 488 | 489 | CH_FORCEINLINE ch::Color operator|(const ch::Color& right) const { 490 | // @SPEED(CHall): I'm lazy 491 | return (s32)*this | (s32)right; 492 | } 493 | 494 | CH_FORCEINLINE void operator|=(const ch::Color& right) { 495 | *this = *this | right; 496 | } 497 | }; 498 | 499 | ch::Stream& operator<<(ch::Stream& stream, const ch::Color& color); 500 | 501 | const ch::Color red = 0xFF0000FF; 502 | const ch::Color green = 0x00FF00FF; 503 | const ch::Color blue = 0x0000FFFF; 504 | const ch::Color white = 0xFFFFFFFF; 505 | const ch::Color black = 0x000000FF; 506 | const ch::Color cyan = green | blue; 507 | const ch::Color yellow = red | green; 508 | const ch::Color magenta = blue | red; 509 | const ch::Color gray = 0x808080FF; 510 | const ch::Color dark_gray = 0x202020FF; 511 | 512 | struct Quaternion { 513 | f32 x, y, z, w; 514 | }; 515 | 516 | struct Matrix4 { 517 | union { 518 | f32 elems[4 * 4]; 519 | f32 row_col[4][4]; 520 | ch::Vector4 rows[4]; 521 | }; 522 | 523 | Matrix4() { ch::mem_zero(elems, sizeof(elems)); } 524 | 525 | f32 operator[](usize index) const { 526 | assert(index < 4 * 4); 527 | return elems[index]; 528 | } 529 | 530 | f32& operator[](usize index) { 531 | assert(index < 4 * 4); 532 | return elems[index]; 533 | } 534 | 535 | ch::Matrix4 operator*(const Matrix4& right) const; 536 | void operator*=(const Matrix4& right); 537 | 538 | ch::Vector4 operator*(const ch::Vector4& right) const; 539 | 540 | operator const f32*() const { return elems; } 541 | operator f32*() { return elems; } 542 | 543 | ch::Matrix4 inverse(); 544 | }; 545 | 546 | ch::Matrix4 identity(); 547 | 548 | ch::Matrix4 ortho(f32 left, f32 right, f32 top, f32 bottom, f32 far, f32 near); 549 | ch::Matrix4 ortho(f32 size, f32 aspect_ratio, f32 far, f32 near); 550 | ch::Matrix4 perspective(f32 fov, f32 aspect_ratio, f32 far, f32 near); 551 | ch::Matrix4 translate(const Vector3& pos); 552 | ch::Matrix4 rotate(f32 angle, const ch::Vector3& axis); 553 | ch::Matrix4 scale(const Vector3& scale); 554 | 555 | } 556 | 557 | u64 hash(ch::Vector2 v); -------------------------------------------------------------------------------- /thirdparty/wglext.h: -------------------------------------------------------------------------------- 1 | #ifndef __wgl_wglext_h_ 2 | #define __wgl_wglext_h_ 1 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | /* 9 | ** Copyright (c) 2013-2018 The Khronos Group Inc. 10 | ** 11 | ** Permission is hereby granted, free of charge, to any person obtaining a 12 | ** copy of this software and/or associated documentation files (the 13 | ** "Materials"), to deal in the Materials without restriction, including 14 | ** without limitation the rights to use, copy, modify, merge, publish, 15 | ** distribute, sublicense, and/or sell copies of the Materials, and to 16 | ** permit persons to whom the Materials are furnished to do so, subject to 17 | ** the following conditions: 18 | ** 19 | ** The above copyright notice and this permission notice shall be included 20 | ** in all copies or substantial portions of the Materials. 21 | ** 22 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 27 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 29 | */ 30 | /* 31 | ** This header is generated from the Khronos OpenGL / OpenGL ES XML 32 | ** API Registry. The current version of the Registry, generator scripts 33 | ** used to make the header, and the header can be found at 34 | ** https://github.com/KhronosGroup/OpenGL-Registry 35 | */ 36 | 37 | #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) 38 | #define WIN32_LEAN_AND_MEAN 1 39 | #include 40 | #endif 41 | 42 | #define WGL_WGLEXT_VERSION 20190728 43 | 44 | /* Generated C header for: 45 | * API: wgl 46 | * Versions considered: .* 47 | * Versions emitted: _nomatch_^ 48 | * Default extensions included: wgl 49 | * Additional extensions included: _nomatch_^ 50 | * Extensions removed: _nomatch_^ 51 | */ 52 | 53 | #ifndef WGL_ARB_buffer_region 54 | #define WGL_ARB_buffer_region 1 55 | #define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 56 | #define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 57 | #define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 58 | #define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 59 | typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); 60 | typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); 61 | typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); 62 | typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); 63 | #ifdef WGL_WGLEXT_PROTOTYPES 64 | HANDLE WINAPI wglCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType); 65 | VOID WINAPI wglDeleteBufferRegionARB (HANDLE hRegion); 66 | BOOL WINAPI wglSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height); 67 | BOOL WINAPI wglRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); 68 | #endif 69 | #endif /* WGL_ARB_buffer_region */ 70 | 71 | #ifndef WGL_ARB_context_flush_control 72 | #define WGL_ARB_context_flush_control 1 73 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 74 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 75 | #define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 76 | #endif /* WGL_ARB_context_flush_control */ 77 | 78 | #ifndef WGL_ARB_create_context 79 | #define WGL_ARB_create_context 1 80 | #define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001 81 | #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 82 | #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 83 | #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 84 | #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 85 | #define WGL_CONTEXT_FLAGS_ARB 0x2094 86 | #define ERROR_INVALID_VERSION_ARB 0x2095 87 | typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList); 88 | #ifdef WGL_WGLEXT_PROTOTYPES 89 | HGLRC WINAPI wglCreateContextAttribsARB (HDC hDC, HGLRC hShareContext, const int *attribList); 90 | #endif 91 | #endif /* WGL_ARB_create_context */ 92 | 93 | #ifndef WGL_ARB_create_context_no_error 94 | #define WGL_ARB_create_context_no_error 1 95 | #define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3 96 | #endif /* WGL_ARB_create_context_no_error */ 97 | 98 | #ifndef WGL_ARB_create_context_profile 99 | #define WGL_ARB_create_context_profile 1 100 | #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 101 | #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 102 | #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 103 | #define ERROR_INVALID_PROFILE_ARB 0x2096 104 | #endif /* WGL_ARB_create_context_profile */ 105 | 106 | #ifndef WGL_ARB_create_context_robustness 107 | #define WGL_ARB_create_context_robustness 1 108 | #define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 109 | #define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252 110 | #define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 111 | #define WGL_NO_RESET_NOTIFICATION_ARB 0x8261 112 | #endif /* WGL_ARB_create_context_robustness */ 113 | 114 | #ifndef WGL_ARB_extensions_string 115 | #define WGL_ARB_extensions_string 1 116 | typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); 117 | #ifdef WGL_WGLEXT_PROTOTYPES 118 | const char *WINAPI wglGetExtensionsStringARB (HDC hdc); 119 | #endif 120 | #endif /* WGL_ARB_extensions_string */ 121 | 122 | #ifndef WGL_ARB_framebuffer_sRGB 123 | #define WGL_ARB_framebuffer_sRGB 1 124 | #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 125 | #endif /* WGL_ARB_framebuffer_sRGB */ 126 | 127 | #ifndef WGL_ARB_make_current_read 128 | #define WGL_ARB_make_current_read 1 129 | #define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 130 | #define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 131 | typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 132 | typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); 133 | #ifdef WGL_WGLEXT_PROTOTYPES 134 | BOOL WINAPI wglMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 135 | HDC WINAPI wglGetCurrentReadDCARB (void); 136 | #endif 137 | #endif /* WGL_ARB_make_current_read */ 138 | 139 | #ifndef WGL_ARB_multisample 140 | #define WGL_ARB_multisample 1 141 | #define WGL_SAMPLE_BUFFERS_ARB 0x2041 142 | #define WGL_SAMPLES_ARB 0x2042 143 | #endif /* WGL_ARB_multisample */ 144 | 145 | #ifndef WGL_ARB_pbuffer 146 | #define WGL_ARB_pbuffer 1 147 | DECLARE_HANDLE(HPBUFFERARB); 148 | #define WGL_DRAW_TO_PBUFFER_ARB 0x202D 149 | #define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E 150 | #define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F 151 | #define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 152 | #define WGL_PBUFFER_LARGEST_ARB 0x2033 153 | #define WGL_PBUFFER_WIDTH_ARB 0x2034 154 | #define WGL_PBUFFER_HEIGHT_ARB 0x2035 155 | #define WGL_PBUFFER_LOST_ARB 0x2036 156 | typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 157 | typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); 158 | typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); 159 | typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); 160 | typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); 161 | #ifdef WGL_WGLEXT_PROTOTYPES 162 | HPBUFFERARB WINAPI wglCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 163 | HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB hPbuffer); 164 | int WINAPI wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC); 165 | BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB hPbuffer); 166 | BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); 167 | #endif 168 | #endif /* WGL_ARB_pbuffer */ 169 | 170 | #ifndef WGL_ARB_pixel_format 171 | #define WGL_ARB_pixel_format 1 172 | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 173 | #define WGL_DRAW_TO_WINDOW_ARB 0x2001 174 | #define WGL_DRAW_TO_BITMAP_ARB 0x2002 175 | #define WGL_ACCELERATION_ARB 0x2003 176 | #define WGL_NEED_PALETTE_ARB 0x2004 177 | #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 178 | #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 179 | #define WGL_SWAP_METHOD_ARB 0x2007 180 | #define WGL_NUMBER_OVERLAYS_ARB 0x2008 181 | #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 182 | #define WGL_TRANSPARENT_ARB 0x200A 183 | #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 184 | #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 185 | #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 186 | #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A 187 | #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B 188 | #define WGL_SHARE_DEPTH_ARB 0x200C 189 | #define WGL_SHARE_STENCIL_ARB 0x200D 190 | #define WGL_SHARE_ACCUM_ARB 0x200E 191 | #define WGL_SUPPORT_GDI_ARB 0x200F 192 | #define WGL_SUPPORT_OPENGL_ARB 0x2010 193 | #define WGL_DOUBLE_BUFFER_ARB 0x2011 194 | #define WGL_STEREO_ARB 0x2012 195 | #define WGL_PIXEL_TYPE_ARB 0x2013 196 | #define WGL_COLOR_BITS_ARB 0x2014 197 | #define WGL_RED_BITS_ARB 0x2015 198 | #define WGL_RED_SHIFT_ARB 0x2016 199 | #define WGL_GREEN_BITS_ARB 0x2017 200 | #define WGL_GREEN_SHIFT_ARB 0x2018 201 | #define WGL_BLUE_BITS_ARB 0x2019 202 | #define WGL_BLUE_SHIFT_ARB 0x201A 203 | #define WGL_ALPHA_BITS_ARB 0x201B 204 | #define WGL_ALPHA_SHIFT_ARB 0x201C 205 | #define WGL_ACCUM_BITS_ARB 0x201D 206 | #define WGL_ACCUM_RED_BITS_ARB 0x201E 207 | #define WGL_ACCUM_GREEN_BITS_ARB 0x201F 208 | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 209 | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 210 | #define WGL_DEPTH_BITS_ARB 0x2022 211 | #define WGL_STENCIL_BITS_ARB 0x2023 212 | #define WGL_AUX_BUFFERS_ARB 0x2024 213 | #define WGL_NO_ACCELERATION_ARB 0x2025 214 | #define WGL_GENERIC_ACCELERATION_ARB 0x2026 215 | #define WGL_FULL_ACCELERATION_ARB 0x2027 216 | #define WGL_SWAP_EXCHANGE_ARB 0x2028 217 | #define WGL_SWAP_COPY_ARB 0x2029 218 | #define WGL_SWAP_UNDEFINED_ARB 0x202A 219 | #define WGL_TYPE_RGBA_ARB 0x202B 220 | #define WGL_TYPE_COLORINDEX_ARB 0x202C 221 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); 222 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); 223 | typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 224 | #ifdef WGL_WGLEXT_PROTOTYPES 225 | BOOL WINAPI wglGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); 226 | BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); 227 | BOOL WINAPI wglChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 228 | #endif 229 | #endif /* WGL_ARB_pixel_format */ 230 | 231 | #ifndef WGL_ARB_pixel_format_float 232 | #define WGL_ARB_pixel_format_float 1 233 | #define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0 234 | #endif /* WGL_ARB_pixel_format_float */ 235 | 236 | #ifndef WGL_ARB_render_texture 237 | #define WGL_ARB_render_texture 1 238 | #define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070 239 | #define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071 240 | #define WGL_TEXTURE_FORMAT_ARB 0x2072 241 | #define WGL_TEXTURE_TARGET_ARB 0x2073 242 | #define WGL_MIPMAP_TEXTURE_ARB 0x2074 243 | #define WGL_TEXTURE_RGB_ARB 0x2075 244 | #define WGL_TEXTURE_RGBA_ARB 0x2076 245 | #define WGL_NO_TEXTURE_ARB 0x2077 246 | #define WGL_TEXTURE_CUBE_MAP_ARB 0x2078 247 | #define WGL_TEXTURE_1D_ARB 0x2079 248 | #define WGL_TEXTURE_2D_ARB 0x207A 249 | #define WGL_MIPMAP_LEVEL_ARB 0x207B 250 | #define WGL_CUBE_MAP_FACE_ARB 0x207C 251 | #define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D 252 | #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E 253 | #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F 254 | #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080 255 | #define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081 256 | #define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082 257 | #define WGL_FRONT_LEFT_ARB 0x2083 258 | #define WGL_FRONT_RIGHT_ARB 0x2084 259 | #define WGL_BACK_LEFT_ARB 0x2085 260 | #define WGL_BACK_RIGHT_ARB 0x2086 261 | #define WGL_AUX0_ARB 0x2087 262 | #define WGL_AUX1_ARB 0x2088 263 | #define WGL_AUX2_ARB 0x2089 264 | #define WGL_AUX3_ARB 0x208A 265 | #define WGL_AUX4_ARB 0x208B 266 | #define WGL_AUX5_ARB 0x208C 267 | #define WGL_AUX6_ARB 0x208D 268 | #define WGL_AUX7_ARB 0x208E 269 | #define WGL_AUX8_ARB 0x208F 270 | #define WGL_AUX9_ARB 0x2090 271 | typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); 272 | typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer); 273 | typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList); 274 | #ifdef WGL_WGLEXT_PROTOTYPES 275 | BOOL WINAPI wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer); 276 | BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer); 277 | BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList); 278 | #endif 279 | #endif /* WGL_ARB_render_texture */ 280 | 281 | #ifndef WGL_ARB_robustness_application_isolation 282 | #define WGL_ARB_robustness_application_isolation 1 283 | #define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008 284 | #endif /* WGL_ARB_robustness_application_isolation */ 285 | 286 | #ifndef WGL_ARB_robustness_share_group_isolation 287 | #define WGL_ARB_robustness_share_group_isolation 1 288 | #endif /* WGL_ARB_robustness_share_group_isolation */ 289 | 290 | #ifndef WGL_3DFX_multisample 291 | #define WGL_3DFX_multisample 1 292 | #define WGL_SAMPLE_BUFFERS_3DFX 0x2060 293 | #define WGL_SAMPLES_3DFX 0x2061 294 | #endif /* WGL_3DFX_multisample */ 295 | 296 | #ifndef WGL_3DL_stereo_control 297 | #define WGL_3DL_stereo_control 1 298 | #define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055 299 | #define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056 300 | #define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057 301 | #define WGL_STEREO_POLARITY_INVERT_3DL 0x2058 302 | typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState); 303 | #ifdef WGL_WGLEXT_PROTOTYPES 304 | BOOL WINAPI wglSetStereoEmitterState3DL (HDC hDC, UINT uState); 305 | #endif 306 | #endif /* WGL_3DL_stereo_control */ 307 | 308 | #ifndef WGL_AMD_gpu_association 309 | #define WGL_AMD_gpu_association 1 310 | #define WGL_GPU_VENDOR_AMD 0x1F00 311 | #define WGL_GPU_RENDERER_STRING_AMD 0x1F01 312 | #define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02 313 | #define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2 314 | #define WGL_GPU_RAM_AMD 0x21A3 315 | #define WGL_GPU_CLOCK_AMD 0x21A4 316 | #define WGL_GPU_NUM_PIPES_AMD 0x21A5 317 | #define WGL_GPU_NUM_SIMD_AMD 0x21A6 318 | #define WGL_GPU_NUM_RB_AMD 0x21A7 319 | #define WGL_GPU_NUM_SPI_AMD 0x21A8 320 | typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids); 321 | typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, INT property, GLenum dataType, UINT size, void *data); 322 | typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc); 323 | typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id); 324 | typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList); 325 | typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc); 326 | typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc); 327 | typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void); 328 | typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); 329 | #ifdef WGL_WGLEXT_PROTOTYPES 330 | UINT WINAPI wglGetGPUIDsAMD (UINT maxCount, UINT *ids); 331 | INT WINAPI wglGetGPUInfoAMD (UINT id, INT property, GLenum dataType, UINT size, void *data); 332 | UINT WINAPI wglGetContextGPUIDAMD (HGLRC hglrc); 333 | HGLRC WINAPI wglCreateAssociatedContextAMD (UINT id); 334 | HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT id, HGLRC hShareContext, const int *attribList); 335 | BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC hglrc); 336 | BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC hglrc); 337 | HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void); 338 | VOID WINAPI wglBlitContextFramebufferAMD (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); 339 | #endif 340 | #endif /* WGL_AMD_gpu_association */ 341 | 342 | #ifndef WGL_ATI_pixel_format_float 343 | #define WGL_ATI_pixel_format_float 1 344 | #define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0 345 | #endif /* WGL_ATI_pixel_format_float */ 346 | 347 | #ifndef WGL_ATI_render_texture_rectangle 348 | #define WGL_ATI_render_texture_rectangle 1 349 | #define WGL_TEXTURE_RECTANGLE_ATI 0x21A5 350 | #endif /* WGL_ATI_render_texture_rectangle */ 351 | 352 | #ifndef WGL_EXT_colorspace 353 | #define WGL_EXT_colorspace 1 354 | #define WGL_COLORSPACE_EXT 0x309D 355 | #define WGL_COLORSPACE_SRGB_EXT 0x3089 356 | #define WGL_COLORSPACE_LINEAR_EXT 0x308A 357 | #endif /* WGL_EXT_colorspace */ 358 | 359 | #ifndef WGL_EXT_create_context_es2_profile 360 | #define WGL_EXT_create_context_es2_profile 1 361 | #define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 362 | #endif /* WGL_EXT_create_context_es2_profile */ 363 | 364 | #ifndef WGL_EXT_create_context_es_profile 365 | #define WGL_EXT_create_context_es_profile 1 366 | #define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004 367 | #endif /* WGL_EXT_create_context_es_profile */ 368 | 369 | #ifndef WGL_EXT_depth_float 370 | #define WGL_EXT_depth_float 1 371 | #define WGL_DEPTH_FLOAT_EXT 0x2040 372 | #endif /* WGL_EXT_depth_float */ 373 | 374 | #ifndef WGL_EXT_display_color_table 375 | #define WGL_EXT_display_color_table 1 376 | typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); 377 | typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); 378 | typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); 379 | typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); 380 | #ifdef WGL_WGLEXT_PROTOTYPES 381 | GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort id); 382 | GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *table, GLuint length); 383 | GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort id); 384 | VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort id); 385 | #endif 386 | #endif /* WGL_EXT_display_color_table */ 387 | 388 | #ifndef WGL_EXT_extensions_string 389 | #define WGL_EXT_extensions_string 1 390 | typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); 391 | #ifdef WGL_WGLEXT_PROTOTYPES 392 | const char *WINAPI wglGetExtensionsStringEXT (void); 393 | #endif 394 | #endif /* WGL_EXT_extensions_string */ 395 | 396 | #ifndef WGL_EXT_framebuffer_sRGB 397 | #define WGL_EXT_framebuffer_sRGB 1 398 | #define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9 399 | #endif /* WGL_EXT_framebuffer_sRGB */ 400 | 401 | #ifndef WGL_EXT_make_current_read 402 | #define WGL_EXT_make_current_read 1 403 | #define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 404 | typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 405 | typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); 406 | #ifdef WGL_WGLEXT_PROTOTYPES 407 | BOOL WINAPI wglMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); 408 | HDC WINAPI wglGetCurrentReadDCEXT (void); 409 | #endif 410 | #endif /* WGL_EXT_make_current_read */ 411 | 412 | #ifndef WGL_EXT_multisample 413 | #define WGL_EXT_multisample 1 414 | #define WGL_SAMPLE_BUFFERS_EXT 0x2041 415 | #define WGL_SAMPLES_EXT 0x2042 416 | #endif /* WGL_EXT_multisample */ 417 | 418 | #ifndef WGL_EXT_pbuffer 419 | #define WGL_EXT_pbuffer 1 420 | DECLARE_HANDLE(HPBUFFEREXT); 421 | #define WGL_DRAW_TO_PBUFFER_EXT 0x202D 422 | #define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E 423 | #define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F 424 | #define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 425 | #define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 426 | #define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 427 | #define WGL_PBUFFER_LARGEST_EXT 0x2033 428 | #define WGL_PBUFFER_WIDTH_EXT 0x2034 429 | #define WGL_PBUFFER_HEIGHT_EXT 0x2035 430 | typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 431 | typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); 432 | typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); 433 | typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); 434 | typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); 435 | #ifdef WGL_WGLEXT_PROTOTYPES 436 | HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); 437 | HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT hPbuffer); 438 | int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC); 439 | BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT hPbuffer); 440 | BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); 441 | #endif 442 | #endif /* WGL_EXT_pbuffer */ 443 | 444 | #ifndef WGL_EXT_pixel_format 445 | #define WGL_EXT_pixel_format 1 446 | #define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 447 | #define WGL_DRAW_TO_WINDOW_EXT 0x2001 448 | #define WGL_DRAW_TO_BITMAP_EXT 0x2002 449 | #define WGL_ACCELERATION_EXT 0x2003 450 | #define WGL_NEED_PALETTE_EXT 0x2004 451 | #define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 452 | #define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 453 | #define WGL_SWAP_METHOD_EXT 0x2007 454 | #define WGL_NUMBER_OVERLAYS_EXT 0x2008 455 | #define WGL_NUMBER_UNDERLAYS_EXT 0x2009 456 | #define WGL_TRANSPARENT_EXT 0x200A 457 | #define WGL_TRANSPARENT_VALUE_EXT 0x200B 458 | #define WGL_SHARE_DEPTH_EXT 0x200C 459 | #define WGL_SHARE_STENCIL_EXT 0x200D 460 | #define WGL_SHARE_ACCUM_EXT 0x200E 461 | #define WGL_SUPPORT_GDI_EXT 0x200F 462 | #define WGL_SUPPORT_OPENGL_EXT 0x2010 463 | #define WGL_DOUBLE_BUFFER_EXT 0x2011 464 | #define WGL_STEREO_EXT 0x2012 465 | #define WGL_PIXEL_TYPE_EXT 0x2013 466 | #define WGL_COLOR_BITS_EXT 0x2014 467 | #define WGL_RED_BITS_EXT 0x2015 468 | #define WGL_RED_SHIFT_EXT 0x2016 469 | #define WGL_GREEN_BITS_EXT 0x2017 470 | #define WGL_GREEN_SHIFT_EXT 0x2018 471 | #define WGL_BLUE_BITS_EXT 0x2019 472 | #define WGL_BLUE_SHIFT_EXT 0x201A 473 | #define WGL_ALPHA_BITS_EXT 0x201B 474 | #define WGL_ALPHA_SHIFT_EXT 0x201C 475 | #define WGL_ACCUM_BITS_EXT 0x201D 476 | #define WGL_ACCUM_RED_BITS_EXT 0x201E 477 | #define WGL_ACCUM_GREEN_BITS_EXT 0x201F 478 | #define WGL_ACCUM_BLUE_BITS_EXT 0x2020 479 | #define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 480 | #define WGL_DEPTH_BITS_EXT 0x2022 481 | #define WGL_STENCIL_BITS_EXT 0x2023 482 | #define WGL_AUX_BUFFERS_EXT 0x2024 483 | #define WGL_NO_ACCELERATION_EXT 0x2025 484 | #define WGL_GENERIC_ACCELERATION_EXT 0x2026 485 | #define WGL_FULL_ACCELERATION_EXT 0x2027 486 | #define WGL_SWAP_EXCHANGE_EXT 0x2028 487 | #define WGL_SWAP_COPY_EXT 0x2029 488 | #define WGL_SWAP_UNDEFINED_EXT 0x202A 489 | #define WGL_TYPE_RGBA_EXT 0x202B 490 | #define WGL_TYPE_COLORINDEX_EXT 0x202C 491 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); 492 | typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); 493 | typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 494 | #ifdef WGL_WGLEXT_PROTOTYPES 495 | BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); 496 | BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); 497 | BOOL WINAPI wglChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); 498 | #endif 499 | #endif /* WGL_EXT_pixel_format */ 500 | 501 | #ifndef WGL_EXT_pixel_format_packed_float 502 | #define WGL_EXT_pixel_format_packed_float 1 503 | #define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8 504 | #endif /* WGL_EXT_pixel_format_packed_float */ 505 | 506 | #ifndef WGL_EXT_swap_control 507 | #define WGL_EXT_swap_control 1 508 | typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); 509 | typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); 510 | #ifdef WGL_WGLEXT_PROTOTYPES 511 | BOOL WINAPI wglSwapIntervalEXT (int interval); 512 | int WINAPI wglGetSwapIntervalEXT (void); 513 | #endif 514 | #endif /* WGL_EXT_swap_control */ 515 | 516 | #ifndef WGL_EXT_swap_control_tear 517 | #define WGL_EXT_swap_control_tear 1 518 | #endif /* WGL_EXT_swap_control_tear */ 519 | 520 | #ifndef WGL_I3D_digital_video_control 521 | #define WGL_I3D_digital_video_control 1 522 | #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 523 | #define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 524 | #define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 525 | #define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 526 | typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); 527 | typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); 528 | #ifdef WGL_WGLEXT_PROTOTYPES 529 | BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue); 530 | BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue); 531 | #endif 532 | #endif /* WGL_I3D_digital_video_control */ 533 | 534 | #ifndef WGL_I3D_gamma 535 | #define WGL_I3D_gamma 1 536 | #define WGL_GAMMA_TABLE_SIZE_I3D 0x204E 537 | #define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F 538 | typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue); 539 | typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue); 540 | typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); 541 | typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); 542 | #ifdef WGL_WGLEXT_PROTOTYPES 543 | BOOL WINAPI wglGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue); 544 | BOOL WINAPI wglSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue); 545 | BOOL WINAPI wglGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue); 546 | BOOL WINAPI wglSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue); 547 | #endif 548 | #endif /* WGL_I3D_gamma */ 549 | 550 | #ifndef WGL_I3D_genlock 551 | #define WGL_I3D_genlock 1 552 | #define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 553 | #define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045 554 | #define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046 555 | #define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047 556 | #define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 557 | #define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 558 | #define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A 559 | #define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B 560 | #define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C 561 | typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC); 562 | typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC); 563 | typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag); 564 | typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource); 565 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource); 566 | typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge); 567 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge); 568 | typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate); 569 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate); 570 | typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay); 571 | typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay); 572 | typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); 573 | #ifdef WGL_WGLEXT_PROTOTYPES 574 | BOOL WINAPI wglEnableGenlockI3D (HDC hDC); 575 | BOOL WINAPI wglDisableGenlockI3D (HDC hDC); 576 | BOOL WINAPI wglIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag); 577 | BOOL WINAPI wglGenlockSourceI3D (HDC hDC, UINT uSource); 578 | BOOL WINAPI wglGetGenlockSourceI3D (HDC hDC, UINT *uSource); 579 | BOOL WINAPI wglGenlockSourceEdgeI3D (HDC hDC, UINT uEdge); 580 | BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge); 581 | BOOL WINAPI wglGenlockSampleRateI3D (HDC hDC, UINT uRate); 582 | BOOL WINAPI wglGetGenlockSampleRateI3D (HDC hDC, UINT *uRate); 583 | BOOL WINAPI wglGenlockSourceDelayI3D (HDC hDC, UINT uDelay); 584 | BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay); 585 | BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay); 586 | #endif 587 | #endif /* WGL_I3D_genlock */ 588 | 589 | #ifndef WGL_I3D_image_buffer 590 | #define WGL_I3D_image_buffer 1 591 | #define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001 592 | #define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002 593 | typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags); 594 | typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress); 595 | typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); 596 | typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count); 597 | #ifdef WGL_WGLEXT_PROTOTYPES 598 | LPVOID WINAPI wglCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags); 599 | BOOL WINAPI wglDestroyImageBufferI3D (HDC hDC, LPVOID pAddress); 600 | BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count); 601 | BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count); 602 | #endif 603 | #endif /* WGL_I3D_image_buffer */ 604 | 605 | #ifndef WGL_I3D_swap_frame_lock 606 | #define WGL_I3D_swap_frame_lock 1 607 | typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void); 608 | typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void); 609 | typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag); 610 | typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag); 611 | #ifdef WGL_WGLEXT_PROTOTYPES 612 | BOOL WINAPI wglEnableFrameLockI3D (void); 613 | BOOL WINAPI wglDisableFrameLockI3D (void); 614 | BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *pFlag); 615 | BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *pFlag); 616 | #endif 617 | #endif /* WGL_I3D_swap_frame_lock */ 618 | 619 | #ifndef WGL_I3D_swap_frame_usage 620 | #define WGL_I3D_swap_frame_usage 1 621 | typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage); 622 | typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void); 623 | typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void); 624 | typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); 625 | #ifdef WGL_WGLEXT_PROTOTYPES 626 | BOOL WINAPI wglGetFrameUsageI3D (float *pUsage); 627 | BOOL WINAPI wglBeginFrameTrackingI3D (void); 628 | BOOL WINAPI wglEndFrameTrackingI3D (void); 629 | BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage); 630 | #endif 631 | #endif /* WGL_I3D_swap_frame_usage */ 632 | 633 | #ifndef WGL_NV_DX_interop 634 | #define WGL_NV_DX_interop 1 635 | #define WGL_ACCESS_READ_ONLY_NV 0x00000000 636 | #define WGL_ACCESS_READ_WRITE_NV 0x00000001 637 | #define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002 638 | typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void *dxObject, HANDLE shareHandle); 639 | typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void *dxDevice); 640 | typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice); 641 | typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access); 642 | typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject); 643 | typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access); 644 | typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects); 645 | typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects); 646 | #ifdef WGL_WGLEXT_PROTOTYPES 647 | BOOL WINAPI wglDXSetResourceShareHandleNV (void *dxObject, HANDLE shareHandle); 648 | HANDLE WINAPI wglDXOpenDeviceNV (void *dxDevice); 649 | BOOL WINAPI wglDXCloseDeviceNV (HANDLE hDevice); 650 | HANDLE WINAPI wglDXRegisterObjectNV (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access); 651 | BOOL WINAPI wglDXUnregisterObjectNV (HANDLE hDevice, HANDLE hObject); 652 | BOOL WINAPI wglDXObjectAccessNV (HANDLE hObject, GLenum access); 653 | BOOL WINAPI wglDXLockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects); 654 | BOOL WINAPI wglDXUnlockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects); 655 | #endif 656 | #endif /* WGL_NV_DX_interop */ 657 | 658 | #ifndef WGL_NV_DX_interop2 659 | #define WGL_NV_DX_interop2 1 660 | #endif /* WGL_NV_DX_interop2 */ 661 | 662 | #ifndef WGL_NV_copy_image 663 | #define WGL_NV_copy_image 1 664 | typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); 665 | #ifdef WGL_WGLEXT_PROTOTYPES 666 | BOOL WINAPI wglCopyImageSubDataNV (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); 667 | #endif 668 | #endif /* WGL_NV_copy_image */ 669 | 670 | #ifndef WGL_NV_delay_before_swap 671 | #define WGL_NV_delay_before_swap 1 672 | typedef BOOL (WINAPI * PFNWGLDELAYBEFORESWAPNVPROC) (HDC hDC, GLfloat seconds); 673 | #ifdef WGL_WGLEXT_PROTOTYPES 674 | BOOL WINAPI wglDelayBeforeSwapNV (HDC hDC, GLfloat seconds); 675 | #endif 676 | #endif /* WGL_NV_delay_before_swap */ 677 | 678 | #ifndef WGL_NV_float_buffer 679 | #define WGL_NV_float_buffer 1 680 | #define WGL_FLOAT_COMPONENTS_NV 0x20B0 681 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1 682 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2 683 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3 684 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4 685 | #define WGL_TEXTURE_FLOAT_R_NV 0x20B5 686 | #define WGL_TEXTURE_FLOAT_RG_NV 0x20B6 687 | #define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7 688 | #define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8 689 | #endif /* WGL_NV_float_buffer */ 690 | 691 | #ifndef WGL_NV_gpu_affinity 692 | #define WGL_NV_gpu_affinity 1 693 | DECLARE_HANDLE(HGPUNV); 694 | struct _GPU_DEVICE { 695 | DWORD cb; 696 | CHAR DeviceName[32]; 697 | CHAR DeviceString[128]; 698 | DWORD Flags; 699 | RECT rcVirtualScreen; 700 | }; 701 | typedef struct _GPU_DEVICE *PGPU_DEVICE; 702 | #define ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0 703 | #define ERROR_MISSING_AFFINITY_MASK_NV 0x20D1 704 | typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu); 705 | typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); 706 | typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList); 707 | typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); 708 | typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc); 709 | #ifdef WGL_WGLEXT_PROTOTYPES 710 | BOOL WINAPI wglEnumGpusNV (UINT iGpuIndex, HGPUNV *phGpu); 711 | BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice); 712 | HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *phGpuList); 713 | BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu); 714 | BOOL WINAPI wglDeleteDCNV (HDC hdc); 715 | #endif 716 | #endif /* WGL_NV_gpu_affinity */ 717 | 718 | #ifndef WGL_NV_multigpu_context 719 | #define WGL_NV_multigpu_context 1 720 | #define WGL_CONTEXT_MULTIGPU_ATTRIB_NV 0x20AA 721 | #define WGL_CONTEXT_MULTIGPU_ATTRIB_SINGLE_NV 0x20AB 722 | #define WGL_CONTEXT_MULTIGPU_ATTRIB_AFR_NV 0x20AC 723 | #define WGL_CONTEXT_MULTIGPU_ATTRIB_MULTICAST_NV 0x20AD 724 | #define WGL_CONTEXT_MULTIGPU_ATTRIB_MULTI_DISPLAY_MULTICAST_NV 0x20AE 725 | #endif /* WGL_NV_multigpu_context */ 726 | 727 | #ifndef WGL_NV_multisample_coverage 728 | #define WGL_NV_multisample_coverage 1 729 | #define WGL_COVERAGE_SAMPLES_NV 0x2042 730 | #define WGL_COLOR_SAMPLES_NV 0x20B9 731 | #endif /* WGL_NV_multisample_coverage */ 732 | 733 | #ifndef WGL_NV_present_video 734 | #define WGL_NV_present_video 1 735 | DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV); 736 | #define WGL_NUM_VIDEO_SLOTS_NV 0x20F0 737 | typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDc, HVIDEOOUTPUTDEVICENV *phDeviceList); 738 | typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); 739 | typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue); 740 | #ifdef WGL_WGLEXT_PROTOTYPES 741 | int WINAPI wglEnumerateVideoDevicesNV (HDC hDc, HVIDEOOUTPUTDEVICENV *phDeviceList); 742 | BOOL WINAPI wglBindVideoDeviceNV (HDC hDc, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList); 743 | BOOL WINAPI wglQueryCurrentContextNV (int iAttribute, int *piValue); 744 | #endif 745 | #endif /* WGL_NV_present_video */ 746 | 747 | #ifndef WGL_NV_render_depth_texture 748 | #define WGL_NV_render_depth_texture 1 749 | #define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3 750 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4 751 | #define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5 752 | #define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6 753 | #define WGL_DEPTH_COMPONENT_NV 0x20A7 754 | #endif /* WGL_NV_render_depth_texture */ 755 | 756 | #ifndef WGL_NV_render_texture_rectangle 757 | #define WGL_NV_render_texture_rectangle 1 758 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0 759 | #define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1 760 | #define WGL_TEXTURE_RECTANGLE_NV 0x20A2 761 | #endif /* WGL_NV_render_texture_rectangle */ 762 | 763 | #ifndef WGL_NV_swap_group 764 | #define WGL_NV_swap_group 1 765 | typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group); 766 | typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier); 767 | typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier); 768 | typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); 769 | typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count); 770 | typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC); 771 | #ifdef WGL_WGLEXT_PROTOTYPES 772 | BOOL WINAPI wglJoinSwapGroupNV (HDC hDC, GLuint group); 773 | BOOL WINAPI wglBindSwapBarrierNV (GLuint group, GLuint barrier); 774 | BOOL WINAPI wglQuerySwapGroupNV (HDC hDC, GLuint *group, GLuint *barrier); 775 | BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers); 776 | BOOL WINAPI wglQueryFrameCountNV (HDC hDC, GLuint *count); 777 | BOOL WINAPI wglResetFrameCountNV (HDC hDC); 778 | #endif 779 | #endif /* WGL_NV_swap_group */ 780 | 781 | #ifndef WGL_NV_vertex_array_range 782 | #define WGL_NV_vertex_array_range 1 783 | typedef void *(WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); 784 | typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer); 785 | #ifdef WGL_WGLEXT_PROTOTYPES 786 | void *WINAPI wglAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); 787 | void WINAPI wglFreeMemoryNV (void *pointer); 788 | #endif 789 | #endif /* WGL_NV_vertex_array_range */ 790 | 791 | #ifndef WGL_NV_video_capture 792 | #define WGL_NV_video_capture 1 793 | DECLARE_HANDLE(HVIDEOINPUTDEVICENV); 794 | #define WGL_UNIQUE_ID_NV 0x20CE 795 | #define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF 796 | typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); 797 | typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList); 798 | typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 799 | typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue); 800 | typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 801 | #ifdef WGL_WGLEXT_PROTOTYPES 802 | BOOL WINAPI wglBindVideoCaptureDeviceNV (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice); 803 | UINT WINAPI wglEnumerateVideoCaptureDevicesNV (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList); 804 | BOOL WINAPI wglLockVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 805 | BOOL WINAPI wglQueryVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue); 806 | BOOL WINAPI wglReleaseVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice); 807 | #endif 808 | #endif /* WGL_NV_video_capture */ 809 | 810 | #ifndef WGL_NV_video_output 811 | #define WGL_NV_video_output 1 812 | DECLARE_HANDLE(HPVIDEODEV); 813 | #define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0 814 | #define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1 815 | #define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2 816 | #define WGL_VIDEO_OUT_COLOR_NV 0x20C3 817 | #define WGL_VIDEO_OUT_ALPHA_NV 0x20C4 818 | #define WGL_VIDEO_OUT_DEPTH_NV 0x20C5 819 | #define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6 820 | #define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7 821 | #define WGL_VIDEO_OUT_FRAME 0x20C8 822 | #define WGL_VIDEO_OUT_FIELD_1 0x20C9 823 | #define WGL_VIDEO_OUT_FIELD_2 0x20CA 824 | #define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB 825 | #define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC 826 | typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); 827 | typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice); 828 | typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); 829 | typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer); 830 | typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); 831 | typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); 832 | #ifdef WGL_WGLEXT_PROTOTYPES 833 | BOOL WINAPI wglGetVideoDeviceNV (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice); 834 | BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV hVideoDevice); 835 | BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer); 836 | BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB hPbuffer, int iVideoBuffer); 837 | BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock); 838 | BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo); 839 | #endif 840 | #endif /* WGL_NV_video_output */ 841 | 842 | #ifndef WGL_OML_sync_control 843 | #define WGL_OML_sync_control 1 844 | typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); 845 | typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator); 846 | typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); 847 | typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); 848 | typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); 849 | typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); 850 | #ifdef WGL_WGLEXT_PROTOTYPES 851 | BOOL WINAPI wglGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc); 852 | BOOL WINAPI wglGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator); 853 | INT64 WINAPI wglSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder); 854 | INT64 WINAPI wglSwapLayerBuffersMscOML (HDC hdc, INT fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder); 855 | BOOL WINAPI wglWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc); 856 | BOOL WINAPI wglWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc); 857 | #endif 858 | #endif /* WGL_OML_sync_control */ 859 | 860 | #ifdef __cplusplus 861 | } 862 | #endif 863 | 864 | #endif 865 | --------------------------------------------------------------------------------