├── .gitignore ├── LICENSE ├── README.md ├── build.bat ├── build.sh ├── examples ├── simple_texture.c ├── simple_triangle.c ├── tetris.c └── ui_showcase.c ├── hi.txt ├── meta.bat ├── meta.sh ├── meta └── table_gen.c ├── project.4coder ├── res ├── Inconsolata.ttf ├── circle.png ├── pepper.png └── shaders │ ├── render_2d.frag.glsl │ ├── render_2d.frag.hlsl │ ├── render_2d.vert.glsl │ ├── render_2d.vert.hlsl │ ├── simple_texture.frag.glsl │ ├── simple_texture.frag.hlsl │ ├── simple_texture.vert.glsl │ ├── simple_texture.vert.hlsl │ ├── simple_triangle.frag.glsl │ ├── simple_triangle.frag.hlsl │ ├── simple_triangle.vert.glsl │ ├── simple_triangle.vert.hlsl │ ├── ui.frag.glsl │ ├── ui.frag.hlsl │ ├── ui.vert.glsl │ └── ui.vert.hlsl ├── source ├── base │ ├── base.h │ ├── ds.h │ ├── log.h │ ├── mem.c │ ├── mem.h │ ├── str.c │ ├── str.h │ ├── tctx.c │ ├── tctx.h │ ├── utils.c │ ├── utils.h │ ├── vmath.c │ └── vmath.h ├── core │ ├── backend.c │ ├── backend.h │ ├── impl │ │ ├── d3d11_functions.c │ │ ├── d3d11_functions.h │ │ ├── d3d11_resources.c │ │ ├── d3d11_resources.h │ │ ├── gl33_resources.c │ │ ├── gl33_resources.h │ │ ├── gl46_resources.c │ │ ├── gl46_resources.h │ │ ├── gl_functions.c │ │ ├── gl_functions.h │ │ ├── linux_gl33_backend.c │ │ ├── linux_gl46_backend.c │ │ ├── win32_d3d11_backend.c │ │ ├── win32_gl33_backend.c │ │ └── win32_gl46_backend.c │ ├── resources.c │ └── resources.h ├── defines.h ├── impl │ ├── ext.c │ └── stb_impl.c ├── main.c ├── opt │ ├── meta │ │ ├── ui_stacks.c │ │ ├── ui_stacks.h │ │ └── ui_stacks.mdesk │ ├── phys_2d.c │ ├── phys_2d.h │ ├── render_2d.c │ ├── render_2d.h │ ├── ui.c │ └── ui.h └── os │ ├── impl │ ├── linux_os.c │ ├── win32_key_code_translate.h │ ├── win32_os.c │ ├── win32_window.c │ ├── win32_window.h │ ├── x11_key_code_translate.h │ ├── x11_window.c │ └── x11_window.h │ ├── input.c │ ├── input.h │ ├── key_codes.h │ ├── os.c │ ├── os.h │ ├── window.c │ └── window.h └── third_party ├── include ├── KHR │ └── khrplatform.h ├── ft2build.h ├── md │ ├── md.h │ └── md_stb_sprintf.h ├── stb │ ├── stb_image.h │ └── stb_truetype.h └── tinyobj │ └── tinyobjloader.h └── source └── md.c /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | meta/.vs/ 3 | meta/table_gen.exe 4 | meta/table_gen 5 | meta/*.pdb 6 | meta/*.ilk 7 | meta/*.sln 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 VoxelRifts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # c-codebase 2 | My Codebase for C programming. 3 | Based a little on https://www.youtube.com/c/Mr4thProgramming but a lot more is added here 4 | 5 | Mainly made to use as few libraries as possible and for my own exploration and use. 6 | 7 | ## What does this codebase have 8 | 9 | - A Base Layer: 10 | - Basic Memory Allocators 11 | - String Utilities 12 | - Thread Context 13 | - Math 14 | - Logging 15 | - Generic Data structure defining macros 16 | - An OS Layer: (Only win32 and x11 linux implemented): 17 | - Basic File handling 18 | - Dynamic Library Loading 19 | - Windowing 20 | - Input 21 | - Timing 22 | - Threading 23 | - A Core Graphics Layer: 24 | - Multiple Backends (OpenGL 3.3, OpenGL 4.6 and D3D11) 25 | - OS Specific Device/Context Creation 26 | - OpenGL Function Loading 27 | - Thin wrapper over backend specific calls (Buffers, Pipelines and Shaders are generic to all backends) 28 | - Several Optional Layers 29 | - Simple 2D Renderer 30 | - User Interface (Somewhat complete) 31 | - Simple 2D Physics (Only collision detection and resolution done. No dynamics yet) 32 | 33 | ## How do I use this codebase? 34 | I would recommend you to make your own :) 35 | However if you still want to: 36 | It has a simple build script file. 37 | Just cd into the directory and run `build.bat` or `build.sh`! 38 | 39 | You need clang OR MSVC installed as I have not tested this with gcc. 40 | AFAIK it should just work with gcc anyways. 41 | 42 | Not tested EXTENSIVELY with linux but the codebase does work 43 | 44 | ## TODOs 45 | - [x] Linux 46 | - [x] Windowing with X11 47 | - [x] Input Handling 48 | - [x] OpenGL 3.3 backend layer 49 | - [x] OpenGL 4.6 backend layer 50 | - [ ] Optional Layers 51 | - [ ] More UI Widgets 52 | - [ ] D3D11 53 | - [ ] Framebuffer support 54 | - [ ] Cleanup 55 | - [ ] Switch from X-Lists to Metaprogram tables for OpenGL function loading 56 | - [ ] Remove Backend specific links (d3d11) by loading functions from dll 57 | - [ ] Major Goals 58 | - [ ] Custom Build system (so I can combine .bat and .sh build files) 59 | 60 | 61 | - [ ] Maybes 62 | - [ ] Implement functions that are insanely tedious (OS_ThreadWaitForAll/Any and others) 63 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @ECHO off 2 | SetLocal EnableDelayedExpansion 3 | IF NOT EXIST bin mkdir bin 4 | IF NOT EXIST bin\int mkdir bin\int 5 | 6 | call vcvarsall.bat x64 7 | SET cc=cl.exe 8 | 9 | REM ------------------ 10 | REM Options 11 | REM ------------------ 12 | 13 | SET Use_Render2D=false 14 | SET Use_Physics2D=false 15 | SET Use_UI=true 16 | 17 | REM ------------------ 18 | REM Main Project 19 | REM ------------------ 20 | 21 | REM ============== 22 | REM Gets list of all C files 23 | SET c_filenames= 24 | FOR %%f in (source\*.c) do SET c_filenames=!c_filenames! %%f 25 | FOR %%f in (source\base\*.c) do SET c_filenames=!c_filenames! %%f 26 | FOR %%f in (source\impl\*.c) do SET c_filenames=!c_filenames! %%f 27 | FOR %%f in (source\core\*.c) do SET c_filenames=!c_filenames! %%f 28 | FOR %%f in (source\os\*.c) do SET c_filenames=!c_filenames! %%f 29 | REM ============== 30 | 31 | REM ============== 32 | REM optional layers 33 | 34 | if %Use_Render2D% == true ( 35 | ECHO Optional Layer Selected: Render2D 36 | SET c_filenames=!c_filenames! source\opt\render_2d.c 37 | ) 38 | 39 | if %Use_Physics2D% == true ( 40 | ECHO Optional Layer Selected: Physics2D 41 | SET c_filenames=!c_filenames! source\opt\phys_2d.c 42 | ) 43 | 44 | if %Use_UI% == true ( 45 | ECHO Optional Layer Selected: UI 46 | SET c_filenames=!c_filenames! source\opt\ui.c 47 | ) 48 | 49 | REM ============== 50 | 51 | 52 | SET backend=BACKEND_D3D11 53 | 54 | 55 | REM ============== 56 | if %cc% == cl.exe ( 57 | SET compiler_flags=/Zc:preprocessor /wd4090 /wd5105 58 | SET include_flags=/I.\source\ /I.\third_party\include\ /I.\third_party\source\ 59 | SET linker_flags=/link /DEBUG /LIBPATH:.\third_party\lib shell32.lib user32.lib winmm.lib userenv.lib gdi32.lib 60 | SET output=/Fe.\bin\codebase /Fo.\bin\int\ 61 | SET defines=/D_DEBUG /D_CRT_SECURE_NO_WARNINGS /D%backend% 62 | ) 63 | 64 | if %cc% == clang ( 65 | SET compiler_flags=-Wall -Wvarargs -Werror -Wno-unused-function -Wno-format-security -Wno-incompatible-pointer-types-discards-qualifiers -Wno-unused-but-set-variable -Wno-int-to-void-pointer-cast 66 | SET include_flags=-Isource -Ithird_party/include -Ithird_party/source 67 | SET linker_flags=-g -lshell32 -luser32 -lwinmm -luserenv -lgdi32 -Lthird_party/lib 68 | SET output=-obin/codebase.exe 69 | SET defines=-D_DEBUG -D_CRT_SECURE_NO_WARNINGS -D%backend% 70 | ) 71 | 72 | REM ============== 73 | 74 | 75 | REM ============== 76 | REM TODO(voxel): REMOVE BACKEND SPECIFIC LINKS 77 | if %backend% == BACKEND_D3D11 ( 78 | if %cc% == cl.exe ( 79 | SET linker_flags=%linker_flags% dxguid.lib d3dcompiler.lib 80 | ) 81 | if %cc% == clang ( 82 | SET linker_flags=%linker_flags% -ldxguid -ld3dcompiler 83 | ) 84 | ) 85 | REM ============== 86 | 87 | REM SET compiler_flags=!compiler_flags! -fsanitize=address 88 | 89 | ECHO Building codebase.exe... 90 | %cc% %compiler_flags% %c_filenames% %defines% %include_flags% %output% %linker_flags% 91 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | if [ ! -d ./bin ]; then 2 | mkdir bin 3 | fi 4 | 5 | cc=clang 6 | 7 | # ------------------ 8 | # Options 9 | # ------------------ 10 | 11 | Use_Render2D=false 12 | Use_Physics2D=false 13 | Use_UI=true 14 | 15 | # ------------------ 16 | # Main Project 17 | # ------------------ 18 | 19 | # ============== 20 | # Gets list of all C files 21 | c_filenames= 22 | for entry in ./source/*.c 23 | do 24 | c_filenames="$c_filenames $entry" 25 | done 26 | 27 | for entry in ./source/base/*.c 28 | do 29 | c_filenames="$c_filenames $entry" 30 | done 31 | 32 | for entry in ./source/impl/*.c 33 | do 34 | c_filenames="$c_filenames $entry" 35 | done 36 | 37 | for entry in ./source/core/*.c 38 | do 39 | c_filenames="$c_filenames $entry" 40 | done 41 | 42 | for entry in ./source/os/*.c 43 | do 44 | c_filenames="$c_filenames $entry" 45 | done 46 | # ============== 47 | 48 | # ============== 49 | # optional layers 50 | 51 | if $Use_Render2D == true 52 | then 53 | echo Optional Layer Selected: Render2D 54 | c_filenames="$c_filenames source/opt/render_2d.c" 55 | fi 56 | 57 | if $Use_Physics2D == true 58 | then 59 | echo Optional Layer Selected: Physics2D 60 | c_filenames="$c_filenames source/opt/phys_2d.c" 61 | fi 62 | 63 | if $Use_UI == true 64 | then 65 | echo Optional Layer Selected: UI 66 | c_filenames="$c_filenames source/opt/ui.c" 67 | fi 68 | 69 | # ============== 70 | 71 | 72 | 73 | # ============== 74 | compiler_flags="-Wall -Wvarargs -Werror -Wno-unused-function -Wno-format-security -Wno-incompatible-pointer-types-discards-qualifiers -Wno-unused-but-set-variable -Wno-int-to-void-pointer-cast" 75 | include_flags="-Isource -Ithird_party/include -Ithird_party/source" 76 | linker_flags="-g -lm -lX11 -Lthird_party/lib" 77 | defines="-D_DEBUG -D_CRT_SECURE_NO_WARNINGS" 78 | output="-obin/codebase" 79 | backend="-DBACKEND_GL46" 80 | # ============== 81 | 82 | 83 | # ============== 84 | # TODO(voxel): REMOVE BACKEND SPECIFIC LINKS 85 | if [ "$backend" = "-DBACKEND_D3D11" ] 86 | then 87 | linker_flags="$linker_flags -ldxguid -ld3dcompiler" 88 | fi 89 | # ============== 90 | 91 | # compiler_flags="$compiler_flags -fsanitize=address" 92 | 93 | echo Building codebase.exe... 94 | $cc $c_filenames $compiler_flags $defines $backend $include_flags $linker_flags $output 95 | -------------------------------------------------------------------------------- /examples/simple_texture.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | #include "os/os.h" 3 | #include "os/window.h" 4 | #include "base/tctx.h" 5 | #include "core/backend.h" 6 | #include "core/resources.h" 7 | 8 | void MyResizeCallback(OS_Window* window, i32 w, i32 h) { 9 | R_Viewport(0, 0, w, h); 10 | } 11 | 12 | int main() { 13 | OS_Init(); 14 | 15 | ThreadContext context = {0}; 16 | tctx_init(&context); 17 | U_FrameArenaInit(); 18 | 19 | OS_Window* window = OS_WindowCreate(1080, 720, str_lit("This should work")); 20 | window->resize_callback = MyResizeCallback; 21 | B_BackendInit(window); 22 | OS_WindowShow(window); 23 | 24 | //- 25 | R_ShaderPack s = {0}; 26 | R_ShaderPackAllocLoad(&s, str_lit("res/shaders/simple_texture")); 27 | 28 | 29 | 30 | R_Attribute attribs[] = { 31 | { str_lit("Position"), AttributeType_Float2 }, 32 | { str_lit("TexCoord"), AttributeType_Float2 }, 33 | }; 34 | 35 | R_Pipeline p = {0}; 36 | R_PipelineAlloc(&p, InputAssembly_Triangles, attribs, ArrayCount(attribs), &s, BlendMode_Alpha); 37 | 38 | 39 | 40 | typedef struct vertex { 41 | vec2 pos; 42 | vec2 tex_coord; 43 | } vertex; 44 | vertex data[] = { 45 | { v2(-.5f, -.5f), v2(0.f, 0.f) }, 46 | { v2( .5f, -.5f), v2(1.f, 0.f) }, 47 | { v2( .5f, .5f), v2(1.f, 1.f) }, 48 | { v2(-.5f, -.5f), v2(0.f, 0.f) }, 49 | { v2( .5f, .5f), v2(1.f, 1.f) }, 50 | { v2(-.5f, .5f), v2(0.f, 1.f) }, 51 | }; 52 | R_Buffer b = {0}; 53 | R_BufferAlloc(&b, BufferFlag_Dynamic | BufferFlag_Type_Vertex, sizeof(vertex)); 54 | R_BufferData(&b, sizeof(data), nullptr); 55 | R_BufferUpdate(&b, 0, sizeof(data), data); 56 | R_PipelineAddBuffer(&p, &b, ArrayCount(attribs)); 57 | 58 | 59 | 60 | string_array u_layout = {0}; 61 | string_array_add(&u_layout, str_lit("val")); 62 | string_array_add(&u_layout, str_lit("color")); 63 | 64 | R_UniformBuffer u = {0}; 65 | R_UniformBufferAlloc(&u, str_lit("TESTBUFFER"), u_layout, &s, ShaderType_Fragment); 66 | R_UniformBufferSetVec4(&u, str_lit("color"), Color_Blue); 67 | R_PipelineAddUniformBuffer(&p, &u); 68 | 69 | string_array_free(&u_layout); 70 | 71 | 72 | R_Texture2D t = {0}; 73 | R_Texture2DAllocLoad(&t, str_lit("res/pepper.png"), TextureResize_Linear, TextureResize_Linear, TextureWrap_Repeat, TextureWrap_Repeat, TextureMutability_Immutable, TextureUsage_ShaderResource); 74 | 75 | 76 | R_ClearColor(.2f, .2f, .2f, 1.f); 77 | 78 | while (OS_WindowIsOpen(window)) { 79 | OS_PollEvents(); 80 | U_ResetFrameArena(); 81 | 82 | B_BackendSelectRenderWindow(window); 83 | R_Clear(BufferMask_Color); 84 | 85 | R_Texture2DBindTo(&t, 0, ShaderType_Fragment); 86 | R_PipelineBind(&p); 87 | 88 | R_Draw(&p, 0, 6); 89 | B_BackendSwapchainNext(window); 90 | } 91 | 92 | R_Texture2DFree(&t); 93 | R_UniformBufferFree(&u); 94 | R_BufferFree(&b); 95 | R_PipelineFree(&p); 96 | R_ShaderPackFree(&s); 97 | 98 | //- 99 | 100 | B_BackendFree(window); 101 | 102 | OS_WindowClose(window); 103 | U_FrameArenaFree(); 104 | tctx_free(&context); 105 | } 106 | 107 | -------------------------------------------------------------------------------- /examples/simple_triangle.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | #include "os/os.h" 3 | #include "os/window.h" 4 | #include "base/tctx.h" 5 | #include "core/backend.h" 6 | #include "core/resources.h" 7 | 8 | void MyResizeCallback(OS_Window* window, i32 w, i32 h) { 9 | R_Viewport(0, 0, w, h); 10 | } 11 | 12 | int main() { 13 | OS_Init(); 14 | 15 | ThreadContext context = {0}; 16 | tctx_init(&context); 17 | U_FrameArenaInit(); 18 | 19 | OS_Window* window = OS_WindowCreate(1080, 720, str_lit("This should work")); 20 | window->resize_callback = MyResizeCallback; 21 | B_BackendInit(window); 22 | OS_WindowShow(window); 23 | 24 | //- 25 | R_ShaderPack s = {0}; 26 | R_ShaderPackAllocLoad(&s, str_lit("res/shaders/simple_texture")); 27 | 28 | R_Attribute attribs[] = { 29 | { str_lit("Position"), AttributeType_Float2 }, 30 | { str_lit("Color"), AttributeType_Float4 }, 31 | }; 32 | 33 | R_Pipeline p = {0}; 34 | R_PipelineAlloc(&p, InputAssembly_Triangles, attribs, ArrayCount(attribs), &s, BlendMode_Alpha); 35 | 36 | typedef struct vertex { 37 | vec2 pos; 38 | vec4 color; 39 | } vertex; 40 | 41 | vertex data[] = { 42 | { v2( 0.f, .5f), v4(.8f, .2f, .3f, 1.f) }, 43 | { v2( .5f, -.5f), v4(.2f, .3f, .8f, 1.f) }, 44 | { v2(-.5f, -.5f), v4(.3f, .8f, .2f, 1.f) }, 45 | }; 46 | 47 | R_Buffer b = {0}; 48 | R_BufferAlloc(&b, BufferFlag_Dynamic | BufferFlag_Type_Vertex, sizeof(vertex)); 49 | R_BufferData(&b, sizeof(data), nullptr); 50 | R_BufferUpdate(&b, 0, sizeof(data), data); 51 | 52 | R_PipelineAddBuffer(&p, &b, ArrayCount(attribs)); 53 | R_ClearColor(.2f, .2f, .2f, 1.f); 54 | 55 | while (OS_WindowIsOpen(window)) { 56 | OS_PollEvents(); 57 | U_ResetFrameArena(); 58 | 59 | B_BackendSelectRenderWindow(window); 60 | R_Clear(BufferMask_Color); 61 | 62 | R_PipelineBind(&p); 63 | R_Draw(&p, 0, 3); 64 | B_BackendSwapchainNext(window); 65 | } 66 | 67 | 68 | R_BufferFree(&b); 69 | R_PipelineFree(&p); 70 | R_ShaderPackFree(&s); 71 | 72 | B_BackendFree(window); 73 | 74 | OS_WindowClose(window); 75 | U_FrameArenaFree(); 76 | tctx_free(&context); 77 | } 78 | -------------------------------------------------------------------------------- /examples/tetris.c: -------------------------------------------------------------------------------- 1 | 2 | //~ 3 | // 4 | // Tetris Example (Followed OLC's tutorial and translated to c) 5 | // Optional Layers Required: Render2D 6 | // 7 | //~ 8 | 9 | #include "defines.h" 10 | #include "os/os.h" 11 | #include "os/window.h" 12 | #include "os/input.h" 13 | #include "base/tctx.h" 14 | #include "core/backend.h" 15 | #include "core/resources.h" 16 | 17 | #include "opt/render_2d.h" 18 | 19 | #include 20 | 21 | DArray_Prototype(i32); 22 | DArray_Impl(i32); 23 | 24 | string_array tetrominos = {0}; 25 | i32 field_width = 12; 26 | i32 field_height = 18; 27 | u8* field; 28 | 29 | f32 xoff = 50; 30 | f32 yoff = 50; 31 | f32 block_size = 20; 32 | 33 | i32 index_with_rotate(i32 x, i32 y, i32 r) { 34 | switch (r % 4) { 35 | case 0: return y * 4 + x; 36 | case 1: return 12 + y - (x * 4); 37 | case 2: return 15 - (y * 4) - x; 38 | case 3: return 3 - y + (x * 4); 39 | } 40 | return 0; 41 | } 42 | 43 | b8 piece_fit_test(u8 id, i32 r, i32 pos_x, i32 pos_y) { 44 | for (i32 y = 0; y < 4; y++) { 45 | for (i32 x = 0; x < 4; x++) { 46 | i32 piece_index = index_with_rotate(x, y, r); 47 | 48 | i32 field_index = (pos_y + y) * field_width + (pos_x + x); 49 | if (pos_x + x >= 0 && pos_x + x < field_width && 50 | pos_y + y >= 0 && pos_y + y < field_height) { 51 | if (tetrominos.elems[id].str[piece_index] == 'X' && field[field_index] != 0) 52 | return false; 53 | } 54 | } 55 | } 56 | return true; 57 | } 58 | 59 | int main() { 60 | OS_Init(); 61 | 62 | ThreadContext context = {0}; 63 | tctx_init(&context); 64 | U_FrameArenaInit(); 65 | 66 | M_Arena global_arena; 67 | arena_init(&global_arena); 68 | 69 | OS_Window* window = OS_WindowCreate(1080, 720, str_lit("This should work")); 70 | B_BackendInit(window); 71 | OS_WindowShow(window); 72 | 73 | R2D_Renderer renderer = {0}; 74 | R2D_Init(window, &renderer); 75 | 76 | vec4 colors[] = { 77 | (vec4) {0}, 78 | Color_Red, 79 | Color_Green, 80 | Color_Blue, 81 | Color_Cyan, 82 | Color_Magenta, 83 | Color_Yellow, 84 | Color_PureRed, 85 | (vec4) {0}, 86 | Color_White, 87 | }; 88 | 89 | string_array_add(&tetrominos, str_lit("..X." "..X." "..X." "..X.")); 90 | string_array_add(&tetrominos, str_lit("..X." ".XX." ".X.." "....")); 91 | string_array_add(&tetrominos, str_lit(".X.." ".XX." "..X." "....")); 92 | string_array_add(&tetrominos, str_lit("...." ".XX." ".XX." "....")); 93 | string_array_add(&tetrominos, str_lit("..X." ".XX." "..X." "....")); 94 | string_array_add(&tetrominos, str_lit("...." ".XX." "..X." "..X.")); 95 | string_array_add(&tetrominos, str_lit("...." ".XX." ".X.." ".X..")); 96 | 97 | field = arena_alloc(&global_arena, sizeof(u8) * field_width * field_height); 98 | 99 | for (u32 y = 0; y < field_height; y++) { 100 | for (u32 x = 0; x < field_width; x++) { 101 | field[y * field_width + x] = 102 | (x == 0 || x == field_width - 1 || y == field_height - 1) 103 | ? 9 : 0; 104 | } 105 | } 106 | 107 | srand(OS_TimeMicrosecondsNow()); 108 | 109 | b8 game_over = false; 110 | i32 current_piece_id = rand() % 7; 111 | i32 current_rotation = 0; 112 | i32 current_x = (field_width / 2) - 1, current_y = 0; 113 | 114 | f32 start, end, dt; 115 | start = OS_TimeMicrosecondsNow(); 116 | 117 | f32 speed = 2; 118 | f32 speed_acc = 0; 119 | 120 | while (OS_WindowIsOpen(window) && !game_over) { 121 | OS_PollEvents(); 122 | U_ResetFrameArena(); 123 | 124 | end = OS_TimeMicrosecondsNow(); 125 | dt = (end - start) / 1e6; 126 | start = OS_TimeMicrosecondsNow(); 127 | 128 | current_x -= (OS_InputKeyPressed(Input_Key_LeftArrow) || OS_InputKeyHeld(Input_Key_LeftArrow)) && piece_fit_test(current_piece_id, current_rotation, current_x - 1, current_y); 129 | current_x += (OS_InputKeyPressed(Input_Key_RightArrow) || OS_InputKeyHeld(Input_Key_RightArrow)) && piece_fit_test(current_piece_id, current_rotation, current_x + 1, current_y); 130 | current_y += 131 | (OS_InputKeyPressed(Input_Key_DownArrow) || OS_InputKeyHeld(Input_Key_DownArrow)) && piece_fit_test(current_piece_id, current_rotation, current_x, current_y + 1); 132 | current_rotation += (OS_InputKeyPressed('Z') || OS_InputKeyHeld('Z')) && piece_fit_test(current_piece_id, current_rotation + 1, current_x, current_y); 133 | 134 | speed_acc += dt; 135 | if (speed_acc >= speed) { 136 | if (piece_fit_test(current_piece_id, current_rotation, current_x, current_y + 1)) 137 | current_y++; 138 | else { 139 | for (u32 y = 0; y < 4; y++) { 140 | for (u32 x = 0; x < 4; x++) { 141 | if (tetrominos.elems[current_piece_id] 142 | .str[index_with_rotate(x, y, current_rotation)] == 'X') { 143 | field[(current_y + y) * field_width + (current_x + x)] = current_piece_id+1; 144 | } 145 | } 146 | } 147 | 148 | darray(i32) fixed_lines = {0}; 149 | for (u32 y = 0; y < 4; y++) { 150 | if (current_y + y < field_height - 1) { 151 | b8 line_destroyed = true; 152 | for (u32 x = 1; x < field_width - 1; x++) { 153 | line_destroyed &= field[(current_y + y) * field_width + x] != 0; 154 | } 155 | if (line_destroyed) { 156 | for (u32 x = 1; x < field_width - 1; x++) { 157 | field[(current_y + y) * field_width + x] = 0; 158 | } 159 | darray_add(i32, &fixed_lines, current_y + y); 160 | } 161 | } 162 | } 163 | Iterate(fixed_lines, i) { 164 | i32 line = fixed_lines.elems[i]; 165 | for (u32 x = 1; x < field_width - 1; x++) { 166 | for (i32 y = line; y > 0; y--) { 167 | field[y * field_width + x] = field[(y - 1) * field_width + x]; 168 | } 169 | field[x] = 0; 170 | } 171 | } 172 | darray_free(i32, &fixed_lines); 173 | 174 | current_x = (field_width / 2) - 1, current_y = 0; 175 | current_piece_id = rand() % 7; 176 | current_rotation = 0; 177 | 178 | if (!piece_fit_test(current_piece_id, current_rotation, current_x, current_y + 1)) { 179 | game_over = true; 180 | } else { 181 | speed = Clamp(0.3, speed - 0.1, 3); 182 | } 183 | } 184 | 185 | speed_acc = 0; 186 | } 187 | 188 | R_Clear(BufferMask_Color); 189 | 190 | R2D_BeginDraw(&renderer); 191 | for (u32 y = 0; y < field_height; y++) { 192 | for (u32 x = 0; x < field_width; x++) { 193 | if (field[y * field_width + x]) 194 | R2D_DrawQuadC(&renderer, 195 | (rect) { xoff + x * block_size, yoff + y * block_size, block_size, block_size }, colors[field[y * field_width + x]]); 196 | } 197 | } 198 | 199 | for (u32 y = 0; y < 4; y++) { 200 | for (u32 x = 0; x < 4; x++) { 201 | if (tetrominos.elems[current_piece_id] 202 | .str[index_with_rotate(x, y, current_rotation)] == 'X') 203 | R2D_DrawQuadC(&renderer, 204 | (rect) { xoff + (current_x + x) * block_size, yoff + (current_y + y) * block_size, block_size, block_size }, 205 | colors[current_piece_id + 1]); 206 | } 207 | } 208 | R2D_EndDraw(&renderer); 209 | 210 | B_BackendSwapchainNext(window); 211 | } 212 | 213 | R2D_Free(&renderer); 214 | 215 | B_BackendFree(window); 216 | OS_WindowClose(window); 217 | 218 | arena_free(&global_arena); 219 | 220 | U_FrameArenaFree(); 221 | tctx_free(&context); 222 | } 223 | -------------------------------------------------------------------------------- /examples/ui_showcase.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | #include "os/os.h" 3 | #include "os/window.h" 4 | #include "os/input.h" 5 | #include "base/tctx.h" 6 | #include "core/backend.h" 7 | #include "core/resources.h" 8 | 9 | #include "opt/ui.h" 10 | 11 | void MyResizeCallback(OS_Window* window, i32 w, i32 h) { 12 | // TODO(voxel): @awkward Add a "first resize" to Win32Window so that This if isn't required 13 | if (window->user_data) { 14 | R_Viewport(0, 0, w, h); 15 | UI_Resize((UI_Cache*) window->user_data, w, h); 16 | } 17 | } 18 | 19 | int main() { 20 | OS_Init(); 21 | 22 | ThreadContext context = {0}; 23 | tctx_init(&context); 24 | 25 | M_Arena global_arena; 26 | arena_init(&global_arena); 27 | 28 | U_FrameArenaInit(); 29 | 30 | OS_Window* window = OS_WindowCreate(1080, 720, str_lit("This should work")); 31 | window->resize_callback = MyResizeCallback; 32 | 33 | B_BackendInit(window); 34 | OS_WindowShow(window); 35 | 36 | UI_Cache* ui_cache = arena_alloc(&global_arena, sizeof(UI_Cache)); 37 | UI_Init(window, ui_cache); 38 | window->user_data = ui_cache; 39 | 40 | f32 start = 0.f; f32 end = 0.016f; 41 | f32 delta = 0.016f; 42 | i32 show_btn = 0; 43 | 44 | while (OS_WindowIsOpen(window)) { 45 | delta = end - start; 46 | start = OS_TimeMicrosecondsNow(); 47 | 48 | U_ResetFrameArena(); 49 | OS_PollEvents(); 50 | 51 | R_Clear(BufferMask_Color); 52 | UI_BeginFrame(window, ui_cache); 53 | 54 | UI_PrefWidth(ui_cache, UI_Percentage(100)) 55 | UI_PrefHeight(ui_cache, UI_Percentage(100)) 56 | UI_LayoutAxis(ui_cache, axis2_x) 57 | { 58 | UI_Box* full_container = UI_BoxMake(ui_cache, BoxFlag_DrawBackground | BoxFlag_DrawBorder | BoxFlag_Clip, str_lit("foo")); 59 | UI_Parent(ui_cache, full_container) { 60 | UI_Spacer(ui_cache, UI_Percentage(35)); 61 | 62 | UI_LayoutAxis(ui_cache, axis2_y) 63 | UI_PrefWidth(ui_cache, UI_Percentage(30)) 64 | UI_PrefHeight(ui_cache, UI_Percentage(100)) { 65 | UI_Box* vert = UI_BoxMake(ui_cache, BoxFlag_DrawBorder | 0, str_lit("VerticalCheckboxContainer")); 66 | 67 | UI_Parent(ui_cache, vert) 68 | UI_PrefWidth(ui_cache, UI_Percentage(100)) 69 | UI_PrefHeight(ui_cache, UI_Pixels(35)) 70 | UI_LayoutAxis(ui_cache, axis2_x) { 71 | UI_Box* pm = UI_BoxMake(ui_cache, 0, str_lit("PlusMinusContainer")); 72 | 73 | UI_Parent(ui_cache, pm) 74 | UI_PrefWidth(ui_cache, UI_Percentage(50)) 75 | UI_PrefHeight(ui_cache, UI_Pixels(35)){ 76 | if (UI_Button(ui_cache, str_lit("+##AddCheckbox")).clicked) 77 | show_btn ++; 78 | if (UI_Button(ui_cache, str_lit("-##SubCheckbox")).clicked) 79 | show_btn --; 80 | if (show_btn < 0) show_btn = 0; 81 | } 82 | 83 | UI_Spacer(ui_cache, UI_Pixels(15)); 84 | 85 | UI_ActiveColor(ui_cache, 0x9A5EBDFF) { 86 | for (i32 i = show_btn; i > 0; i--) 87 | UI_CheckboxF(ui_cache, "Checkbox##%d", i); 88 | } 89 | } 90 | 91 | } 92 | } 93 | } 94 | 95 | UI_EndFrame(ui_cache, delta / 1e6); 96 | 97 | B_BackendSwapchainNext(window); 98 | 99 | end = OS_TimeMicrosecondsNow(); 100 | } 101 | 102 | B_BackendFree(window); 103 | 104 | OS_WindowClose(window); 105 | 106 | U_FrameArenaFree(); 107 | arena_free(&global_arena); 108 | tctx_free(&context); 109 | } 110 | -------------------------------------------------------------------------------- /hi.txt: -------------------------------------------------------------------------------- 1 | TEST -------------------------------------------------------------------------------- /meta.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | SET cc=clang 4 | 5 | REM ------------------ 6 | REM Metaprograms 7 | REM ------------------ 8 | 9 | SET compiler_flags=-Wall -Wvarargs -Werror -Wno-unused-but-set-variable -Wno-unused-function 10 | SET include_flags=-Isource -Ithird_party/include -Ithird_party/source 11 | SET linker_flags=-g -Lthird_party/lib 12 | SET defines=-D_DEBUG -D_CRT_SECURE_NO_WARNINGS 13 | SET output=-ometa/table_gen.exe 14 | 15 | ECHO Building table_gen.exe... 16 | %cc% meta/table_gen.c %compiler_flags% %defines% %include_flags% %linker_flags% %output% 17 | 18 | 19 | ECHO Running Metaprogram on source\opt\meta\ui_stacks.mdesk 20 | meta\table_gen.exe "source\opt\meta\ui_stacks.mdesk" 21 | -------------------------------------------------------------------------------- /meta.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cc=gcc 4 | 5 | # ------------------ 6 | # Metaprograms 7 | # ------------------ 8 | 9 | compiler_flags="-Wall -Wvarargs -Werror -Wno-unused-but-set-variable -Wno-unused-function" 10 | include_flags="-Isource -Ithird_party/include -Ithird_party/source" 11 | linker_flags="-g -Lthird_party/lib" 12 | defines="-D_DEBUG -D_CRT_SECURE_NO_WARNINGS" 13 | output="-ometa/table_gen" 14 | 15 | echo Building table_gen.exe... 16 | $cc meta/table_gen.c $compiler_flags $defines $include_flags $linker_flags $output 17 | 18 | 19 | echo Running Metaprogram on source/opt/meta/ui_stacks.mdesk 20 | meta/table_gen "source/opt/meta/ui_stacks.mdesk" 21 | -------------------------------------------------------------------------------- /project.4coder: -------------------------------------------------------------------------------- 1 | version(1); 2 | 3 | project_name = "Codebase"; 4 | 5 | patterns = { 6 | "*.c", 7 | "*.cpp", 8 | "*.mdesk", 9 | "*.h", 10 | "*.bat", 11 | "*.sh", 12 | "*.4coder", 13 | "*.txt", 14 | "*.glsl", 15 | }; 16 | 17 | blacklist_patterns = { 18 | ".*", 19 | }; 20 | 21 | load_paths_custom = { 22 | { "./source" }, 23 | { "./third_party/include/KHR" }, 24 | { "./third_party/include/md" }, 25 | { "./third_party/include/stb" }, 26 | { "./third_party/source" }, 27 | // { "./third_party/include/freetype" }, 28 | // { "./third_party/include/dlg" }, 29 | { "./", .recursive = false }, 30 | }; 31 | 32 | load_paths = { 33 | { load_paths_custom, .os = "win" }, 34 | { load_paths_custom, .os = "linux" }, 35 | }; 36 | 37 | command_list = { 38 | { 39 | .name = "build", 40 | .out = "*compilation*", 41 | .footer_panel = true, 42 | .save_dirty_files = true, 43 | .cursor_at_end = false, 44 | .cmd = 45 | { 46 | { "build.bat", .os = "win" }, 47 | { "./build.sh", .os = "linux" }, 48 | }, 49 | }, 50 | { 51 | .name = "run", 52 | .out = "*compilation*", 53 | .footer_panel = true, 54 | .save_dirty_files = true, 55 | .cursor_at_end = true, 56 | .cmd = 57 | { 58 | { "bin\codebase.exe", .os = "win" }, 59 | { "bin/codebase", .os = "linux" }, 60 | }, 61 | }, 62 | { 63 | .name = "run-metaprograms", 64 | .out = "*compilation*", 65 | .footer_panel = true, 66 | .save_dirty_files = true, 67 | .cursor_at_end = false, 68 | .cmd = 69 | { 70 | { "meta.bat", .os = "win" }, 71 | { "./meta.sh", .os = "linux" }, 72 | }, 73 | }, 74 | }; 75 | 76 | fkey_command[1] = "build"; 77 | fkey_command[2] = "run"; 78 | fkey_command[3] = "run-metaprograms"; 79 | -------------------------------------------------------------------------------- /res/Inconsolata.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PixelRifts/c-codebase/de09f86e53fc218165ac6bf5bd0c9bc1457aa4f1/res/Inconsolata.ttf -------------------------------------------------------------------------------- /res/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PixelRifts/c-codebase/de09f86e53fc218165ac6bf5bd0c9bc1457aa4f1/res/circle.png -------------------------------------------------------------------------------- /res/pepper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PixelRifts/c-codebase/de09f86e53fc218165ac6bf5bd0c9bc1457aa4f1/res/pepper.png -------------------------------------------------------------------------------- /res/shaders/render_2d.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in float v_texindex; 4 | in vec2 v_texcoord; 5 | in vec4 v_color; 6 | 7 | layout (location = 0) out vec4 f_color; 8 | 9 | uniform sampler2D u_tex[8]; 10 | 11 | void main() { 12 | switch (int(v_texindex)) { 13 | case 0: f_color = v_color * texture(u_tex[0], v_texcoord); break; 14 | case 1: f_color = v_color * texture(u_tex[1], v_texcoord); break; 15 | case 2: f_color = v_color * texture(u_tex[2], v_texcoord); break; 16 | case 3: f_color = v_color * texture(u_tex[3], v_texcoord); break; 17 | case 4: f_color = v_color * texture(u_tex[4], v_texcoord); break; 18 | case 5: f_color = v_color * texture(u_tex[5], v_texcoord); break; 19 | case 6: f_color = v_color * texture(u_tex[6], v_texcoord); break; 20 | case 7: f_color = v_color * texture(u_tex[7], v_texcoord); break; 21 | default: discard; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /res/shaders/render_2d.frag.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D te0 : register(t0); 2 | Texture2D te1 : register(t1); 3 | Texture2D te2 : register(t2); 4 | Texture2D te3 : register(t3); 5 | Texture2D te4 : register(t4); 6 | Texture2D te5 : register(t5); 7 | Texture2D te6 : register(t6); 8 | Texture2D te7 : register(t7); 9 | 10 | SamplerState se0 : register(s0); 11 | SamplerState se1 : register(s1); 12 | SamplerState se2 : register(s2); 13 | SamplerState se3 : register(s3); 14 | SamplerState se4 : register(s4); 15 | SamplerState se5 : register(s5); 16 | SamplerState se6 : register(s6); 17 | SamplerState se7 : register(s7); 18 | 19 | float4 main( 20 | float1 tex_idx : TexIndex, 21 | float2 tex_coord : TexCoord, 22 | float4 color : Color 23 | ) : SV_Target { 24 | 25 | [branch] switch (int(tex_idx)) { 26 | case 0: return color * te0.Sample(se0, tex_coord); 27 | case 1: return color * te1.Sample(se1, tex_coord); 28 | case 2: return color * te2.Sample(se2, tex_coord); 29 | case 3: return color * te3.Sample(se3, tex_coord); 30 | case 4: return color * te4.Sample(se4, tex_coord); 31 | case 5: return color * te5.Sample(se5, tex_coord); 32 | case 6: return color * te6.Sample(se6, tex_coord); 33 | case 7: return color * te7.Sample(se7, tex_coord); 34 | default: discard; break; 35 | } 36 | return float4(1, 1, 1, 1); 37 | } 38 | -------------------------------------------------------------------------------- /res/shaders/render_2d.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location = 0) in vec2 a_pos; 4 | layout (location = 1) in vec2 a_texcoord; 5 | layout (location = 2) in float a_texindex; 6 | layout (location = 3) in vec4 a_color; 7 | 8 | out float v_texindex; 9 | out vec2 v_texcoord; 10 | out vec4 v_color; 11 | 12 | 13 | layout (std140) uniform ActualConstants { 14 | mat4 u_projection; 15 | }; 16 | 17 | void main() { 18 | gl_Position = u_projection * vec4(a_pos, 0.0, 1.0); 19 | v_texindex = a_texindex; 20 | v_texcoord = a_texcoord; 21 | v_color = a_color; 22 | } 23 | -------------------------------------------------------------------------------- /res/shaders/render_2d.vert.hlsl: -------------------------------------------------------------------------------- 1 | 2 | struct VS_Out { 3 | float1 tex_idx : TexIndex; 4 | float2 tex_coord : TexCoord; 5 | float4 color : Color; 6 | float4 pos : SV_Position; 7 | }; 8 | 9 | cbuffer ActualConstants { 10 | matrix u_projection; 11 | }; 12 | 13 | VS_Out main( 14 | float2 pos : Position, 15 | float2 tex_coord : TexCoord, 16 | float1 tex_idx : TexIndex, 17 | float4 color : Color 18 | ) { 19 | VS_Out ret; 20 | ret.pos = mul(u_projection, float4(pos, 0.0, 1.0)); 21 | ret.tex_idx = tex_idx; 22 | ret.tex_coord = tex_coord; 23 | ret.color = color; 24 | return ret; 25 | } 26 | -------------------------------------------------------------------------------- /res/shaders/simple_texture.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location=0) out vec4 f_color; 4 | 5 | in vec2 v_tex_coord; 6 | 7 | uniform sampler2D tex; 8 | 9 | layout (std140) uniform TESTBUFFER { 10 | float val; 11 | vec4 color; 12 | }; 13 | 14 | void main() { 15 | f_color = color * texture(tex, v_tex_coord); 16 | } 17 | -------------------------------------------------------------------------------- /res/shaders/simple_texture.frag.hlsl: -------------------------------------------------------------------------------- 1 | 2 | Texture2D t : register(t0); 3 | SamplerState t_sampler : register(s0); 4 | 5 | cbuffer TESTBUFFER { 6 | float1 val; 7 | float4 color; 8 | }; 9 | 10 | float4 main(float2 tex_coord : TexCoord) : SV_Target { 11 | return color * t.Sample(t_sampler, tex_coord); 12 | } 13 | -------------------------------------------------------------------------------- /res/shaders/simple_texture.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location=0) in vec2 a_pos; 4 | layout (location=1) in vec2 a_tex_coord; 5 | 6 | out vec2 v_tex_coord; 7 | 8 | void main() { 9 | gl_Position = vec4(a_pos, 0.0, 1.0); 10 | v_tex_coord = a_tex_coord; 11 | } 12 | -------------------------------------------------------------------------------- /res/shaders/simple_texture.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct VS_Out { 2 | float2 tex_coord : TexCoord; 3 | float4 pos : SV_Position; 4 | }; 5 | 6 | VS_Out main(float2 pos : Position, float2 tex_coord : TexCoord) { 7 | VS_Out ret; 8 | ret.pos = float4(pos.x, pos.y, 0.0, 1.0); 9 | ret.tex_coord = tex_coord; 10 | return ret; 11 | } 12 | -------------------------------------------------------------------------------- /res/shaders/simple_triangle.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location=0) out vec4 f_color; 4 | 5 | in vec4 v_color; 6 | 7 | void main() { 8 | f_color = v_color; 9 | } 10 | -------------------------------------------------------------------------------- /res/shaders/simple_triangle.frag.hlsl: -------------------------------------------------------------------------------- 1 | float4 main(float4 color : Color) : SV_Target { 2 | return color; 3 | } 4 | -------------------------------------------------------------------------------- /res/shaders/simple_triangle.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location=0) in vec2 a_pos; 4 | layout (location=1) in vec4 a_color; 5 | 6 | out vec4 v_color; 7 | 8 | void main() { 9 | gl_Position = vec4(a_pos, 0.0, 1.0); 10 | v_color = a_color; 11 | } 12 | -------------------------------------------------------------------------------- /res/shaders/simple_triangle.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct VS_Out { 2 | float4 color : Color; 3 | float4 pos : SV_Position; 4 | }; 5 | 6 | VS_Out main(float2 pos : Position, float4 color : Color) { 7 | VS_Out ret; 8 | ret.pos = float4(pos.x, pos.y, 0.0, 1.0); 9 | ret.color = color; 10 | return ret; 11 | } 12 | -------------------------------------------------------------------------------- /res/shaders/ui.frag.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec2 v_boxsize; 4 | in vec2 v_boxcenter; 5 | in float v_texindex; 6 | in vec2 v_texcoord; 7 | in vec4 v_color; 8 | in vec4 v_clip_quad; 9 | in vec3 v_rounding_softness_and_edge_size; 10 | in vec2 v_sampling_loc; 11 | 12 | layout (location = 0) out vec4 f_color; 13 | 14 | uniform sampler2D u_tex[8]; 15 | 16 | // Thanks a LOT Ryan :D. This is so much nicer rounding than I was using before 17 | // +Edges is a nice feature 18 | 19 | float RoundedRectSDF(vec2 sample_pos, vec2 rect_center, vec2 rect_half_size, float r) { 20 | vec2 d2 = (abs(rect_center - sample_pos) - rect_half_size + vec2(r, r)); 21 | return min(max(d2.x, d2.y), 0.0) + length(max(d2, 0.0)) - r; 22 | } 23 | 24 | bool rect_contains_point(vec4 a, vec2 p) { 25 | return a.x <= p.x && a.y <= p.y && a.x + a.z >= p.x && a.y + a.w >= p.y; 26 | } 27 | 28 | void main() { 29 | vec2 half_boxsize = v_boxsize / 2.0; 30 | if (!rect_contains_point(v_clip_quad, v_sampling_loc)) discard; 31 | 32 | // Texture 33 | switch (int(v_texindex)) { 34 | case 0: f_color = texture(u_tex[0], v_texcoord); break; 35 | case 1: f_color = texture(u_tex[1], v_texcoord); break; 36 | case 2: f_color = texture(u_tex[2], v_texcoord); break; 37 | case 3: f_color = texture(u_tex[3], v_texcoord); break; 38 | case 4: f_color = texture(u_tex[4], v_texcoord); break; 39 | case 5: f_color = texture(u_tex[5], v_texcoord); break; 40 | case 6: f_color = texture(u_tex[6], v_texcoord); break; 41 | case 7: f_color = texture(u_tex[7], v_texcoord); break; 42 | default: discard; 43 | } 44 | 45 | 46 | // Color 47 | f_color *= v_color; 48 | 49 | 50 | // Rounding 51 | 52 | float softness = v_rounding_softness_and_edge_size.y; 53 | vec2 softness_padding = vec2(max(0, softness*2-1), max(0, softness*2-1)); 54 | 55 | float dist = RoundedRectSDF(v_sampling_loc, v_boxcenter, 56 | half_boxsize-softness_padding, 57 | v_rounding_softness_and_edge_size.x); 58 | float sdf_factor = 1.0 - smoothstep(0, 2*softness, dist); 59 | 60 | f_color *= sdf_factor; 61 | 62 | 63 | // Edges 64 | float edge_size = v_rounding_softness_and_edge_size.z; 65 | if (edge_size != 0) { 66 | vec2 interior_half_size = half_boxsize - vec2(edge_size); 67 | 68 | float interior_radius_reduce_f = min(interior_half_size.x/half_boxsize.x, 69 | interior_half_size.y/half_boxsize.y); 70 | 71 | float interior_corner_radius = (v_rounding_softness_and_edge_size.x 72 | * interior_radius_reduce_f * interior_radius_reduce_f); 73 | 74 | float inside_d = RoundedRectSDF(v_sampling_loc, v_boxcenter, 75 | interior_half_size-softness_padding, 76 | interior_corner_radius); 77 | f_color *= smoothstep(0, 2*softness, inside_d); 78 | } 79 | 80 | 81 | //f_color = vec4(edge_size / 100.f, 0.2, 0.3, 1.0); 82 | } 83 | -------------------------------------------------------------------------------- /res/shaders/ui.frag.hlsl: -------------------------------------------------------------------------------- 1 | Texture2D te0 : register(t0); 2 | Texture2D te1 : register(t1); 3 | Texture2D te2 : register(t2); 4 | Texture2D te3 : register(t3); 5 | Texture2D te4 : register(t4); 6 | Texture2D te5 : register(t5); 7 | Texture2D te6 : register(t6); 8 | Texture2D te7 : register(t7); 9 | 10 | SamplerState se0 : register(s0); 11 | SamplerState se1 : register(s1); 12 | SamplerState se2 : register(s2); 13 | SamplerState se3 : register(s3); 14 | SamplerState se4 : register(s4); 15 | SamplerState se5 : register(s5); 16 | SamplerState se6 : register(s6); 17 | SamplerState se7 : register(s7); 18 | 19 | float1 RoundedRectSDF(float2 sample_pos, float2 rect_center, float2 rect_half_size, float1 r) { 20 | float2 d2 = (abs(rect_center - sample_pos) - rect_half_size + float2(r, r)); 21 | return min(max(d2.x, d2.y), 0.0) + length(max(d2, 0.0)) - r; 22 | } 23 | 24 | bool rect_contains_point(float4 a, float2 p) { 25 | return a.x <= p.x && a.y <= p.y && a.x + a.z >= p.x && a.y + a.w >= p.y; 26 | } 27 | 28 | float4 main( 29 | float2 size : BoxSize, 30 | float2 center : BoxCenter, 31 | float1 tex_idx : TexIndex, 32 | float2 tex_coord : TexCoord, 33 | float4 color : Color, 34 | float4 clip_quad : ClipQuad, 35 | float3 rounding_softness_and_edgesize : RoundingSoftnessAndEdgeSize, 36 | float2 sampling_loc : SamplingLoc 37 | ) : SV_Target { 38 | float2 half_boxsize = size / 2.0; 39 | if (!rect_contains_point(clip_quad, sampling_loc)) { 40 | discard; 41 | return float4(1, 1, 1, 1); 42 | } 43 | 44 | float4 final_color = float4(0, 0, 0, 0); 45 | [branch] switch (int(tex_idx)) { 46 | case 0: final_color = color * te0.Sample(se0, tex_coord); break; 47 | case 1: final_color = color * te1.Sample(se1, tex_coord); break; 48 | case 2: final_color = color * te2.Sample(se2, tex_coord); break; 49 | case 3: final_color = color * te3.Sample(se3, tex_coord); break; 50 | case 4: final_color = color * te4.Sample(se4, tex_coord); break; 51 | case 5: final_color = color * te5.Sample(se5, tex_coord); break; 52 | case 6: final_color = color * te6.Sample(se6, tex_coord); break; 53 | case 7: final_color = color * te7.Sample(se7, tex_coord); break; 54 | default: discard; return float4(1, 1, 1, 1); 55 | } 56 | 57 | // Rounding 58 | float1 softness = rounding_softness_and_edgesize.y; 59 | float2 softness_padding = float2(max(0, softness*2-1), max(0, softness*2-1)); 60 | float1 dist = RoundedRectSDF(sampling_loc, center, half_boxsize-softness_padding, 61 | rounding_softness_and_edgesize.x); 62 | float1 sdf_factor = 1.0 - smoothstep(0, 2*softness, dist); 63 | final_color *= sdf_factor; 64 | 65 | 66 | // Edges 67 | float1 edge_size = rounding_softness_and_edgesize.z; 68 | if (edge_size != 0) { 69 | float2 interior_half_size = half_boxsize - float2(edge_size, edge_size); 70 | 71 | float1 interior_radius_reduce_f = min(interior_half_size.x/half_boxsize.x, 72 | interior_half_size.y/half_boxsize.y); 73 | 74 | float1 interior_corner_radius = (rounding_softness_and_edgesize.x 75 | * interior_radius_reduce_f * interior_radius_reduce_f); 76 | 77 | float1 inside_d = RoundedRectSDF(sampling_loc, center, interior_half_size-softness_padding, 78 | interior_corner_radius); 79 | final_color *= smoothstep(0, 2*softness, inside_d); 80 | } 81 | return final_color; 82 | } 83 | -------------------------------------------------------------------------------- /res/shaders/ui.vert.glsl: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | layout (location = 0) in vec2 a_boxsize; 4 | layout (location = 1) in vec2 a_boxcenter; 5 | layout (location = 2) in vec2 a_uv; 6 | layout (location = 3) in float a_texidx; 7 | layout (location = 4) in vec4 a_color; 8 | layout (location = 5) in vec4 a_clip_quad; 9 | layout (location = 6) in vec3 a_rounding_softness_and_edge_size; 10 | 11 | out vec2 v_boxsize; 12 | out vec2 v_boxcenter; 13 | out float v_texindex; 14 | out vec2 v_texcoord; 15 | out vec4 v_color; 16 | out vec4 v_clip_quad; 17 | out vec3 v_rounding_softness_and_edge_size; 18 | out vec2 v_sampling_loc; 19 | 20 | const vec2 vertex_multiplers[6] = vec2[6]( 21 | vec2(-.5, -.5), 22 | vec2(+.5, -.5), 23 | vec2(+.5, +.5), 24 | vec2(-.5, -.5), 25 | vec2(+.5, +.5), 26 | vec2(-.5, +.5) 27 | ); 28 | 29 | layout (std140) uniform ActualConstants { 30 | mat4 u_projection; 31 | }; 32 | 33 | void main() { 34 | vec2 pos = a_boxcenter + (a_boxsize * vertex_multiplers[gl_VertexID % 6]); 35 | gl_Position = u_projection * vec4(pos, 0.0, 1.0); 36 | v_boxsize = a_boxsize; 37 | v_boxcenter = a_boxcenter; 38 | v_texindex = a_texidx; 39 | v_texcoord = a_uv; 40 | v_color = a_color; 41 | v_clip_quad = a_clip_quad; 42 | v_rounding_softness_and_edge_size = a_rounding_softness_and_edge_size; 43 | v_sampling_loc = pos; 44 | } 45 | -------------------------------------------------------------------------------- /res/shaders/ui.vert.hlsl: -------------------------------------------------------------------------------- 1 | struct VS_Out { 2 | float2 size : BoxSize; 3 | float2 center : BoxCenter; 4 | float1 tex_idx : TexIndex; 5 | float2 tex_coord : TexCoord; 6 | float4 color : Color; 7 | float4 clip_quad : ClipQuad; 8 | float3 rounding_softness_and_edgesize : RoundingSoftnessAndEdgeSize; 9 | float2 sampling_loc : SamplingLoc; 10 | 11 | float4 pos : SV_Position; 12 | }; 13 | 14 | cbuffer ActualConstants { 15 | matrix u_projection; 16 | }; 17 | 18 | static const float2 vertex_multiplers[] = { 19 | float2(-.5, -.5), 20 | float2(+.5, -.5), 21 | float2(+.5, +.5), 22 | float2(-.5, -.5), 23 | float2(+.5, +.5), 24 | float2(-.5, +.5), 25 | }; 26 | 27 | VS_Out main( 28 | float2 size : BoxSize, 29 | float2 center : BoxCenter, 30 | float2 tex_coord : TexCoord, 31 | float1 tex_idx : TexIndex, 32 | float4 color : Color, 33 | float4 clip_quad : ClipQuad, 34 | float3 rounding_softness_and_edgesize : RoundingSoftnessAndEdgeSize, 35 | uint vertex_id : SV_VertexID 36 | ) { 37 | VS_Out ret; 38 | float2 pos = center + (size * vertex_multiplers[vertex_id % 6]); 39 | 40 | ret.pos = mul(u_projection, float4(pos, 0.0, 1.0)); 41 | ret.size = size; 42 | ret.center = center; 43 | ret.tex_idx = tex_idx; 44 | ret.tex_coord = tex_coord; 45 | ret.color = color; 46 | ret.clip_quad = clip_quad; 47 | ret.rounding_softness_and_edgesize = rounding_softness_and_edgesize; 48 | ret.sampling_loc = pos; 49 | return ret; 50 | } 51 | -------------------------------------------------------------------------------- /source/base/base.h: -------------------------------------------------------------------------------- 1 | /* date = July 3rd 2022 11:23 am */ 2 | 3 | #ifndef BASE_H 4 | #define BASE_H 5 | 6 | #include "defines.h" 7 | #include "ds.h" 8 | #include "log.h" 9 | #include "mem.h" 10 | #include "str.h" 11 | #include "tctx.h" 12 | #include "utils.h" 13 | #include "vmath.h" 14 | 15 | #endif //BASE_H 16 | -------------------------------------------------------------------------------- /source/base/log.h: -------------------------------------------------------------------------------- 1 | /* date = July 3rd 2022 11:22 am */ 2 | 3 | #ifndef LOG_H 4 | #define LOG_H 5 | 6 | #include "defines.h" 7 | 8 | // TODO(voxel): assert should actually do a debug break. 9 | 10 | #if defined(_DEBUG) 11 | 12 | 13 | # define Log(format, ...) Statement(\ 14 | printf("Info: ");\ 15 | printf(format, ##__VA_ARGS__);\ 16 | printf("\n");\ 17 | flush;\ 18 | ) 19 | # define LogError(format, ...) Statement(\ 20 | printf("%s:%d: Error: ", FILE_NAME, __LINE__);\ 21 | printf(format, ##__VA_ARGS__);\ 22 | printf("\n");\ 23 | flush;\ 24 | ) 25 | # define LogReturn(ret, format, ...) Statement(\ 26 | printf("%s:%d: Error: ", FILE_NAME, __LINE__);\ 27 | printf(format, ##__VA_ARGS__);\ 28 | printf("\n");\ 29 | flush;\ 30 | return ret;\ 31 | ) 32 | # define LogFatal(format, ...) Statement(\ 33 | printf("%s:%d: Error: ", FILE_NAME, __LINE__);\ 34 | printf(format, ##__VA_ARGS__);\ 35 | printf("\n");\ 36 | flush;\ 37 | exit(-1);\ 38 | ) 39 | # define AssertTrue(c, format, ...) Statement(\ 40 | if (!(c)) {\ 41 | printf("%s:%d: Error: ", FILE_NAME, __LINE__);\ 42 | printf("Assertion Failure: ");\ 43 | printf(format, ##__VA_ARGS__);\ 44 | printf("\n");\ 45 | }\ 46 | ) 47 | 48 | 49 | 50 | #else 51 | # define Log(format, ...) Statement() 52 | # define LogError(format, ...) Statement() 53 | # define LogReturn(ret, format, ...) Statement() 54 | # define LogFatal(format, ...) Statement() 55 | # define AssertTrue(c, format, ...) Statement() 56 | #endif // DEBUG 57 | 58 | #endif //LOG_H 59 | -------------------------------------------------------------------------------- /source/base/mem.c: -------------------------------------------------------------------------------- 1 | #include "mem.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // Dependency on the OS. Although it is generic 8 | #include "os/os.h" 9 | 10 | #define DEFAULT_ALIGNMENT sizeof(void*) 11 | 12 | b8 is_power_of_two(uintptr_t x) { 13 | return (x & (x-1)) == 0; 14 | } 15 | 16 | u64 align_forward_u64(u64 ptr, u64 align) { 17 | u64 p, a, modulo; 18 | 19 | assert(is_power_of_two(align)); 20 | 21 | p = ptr; 22 | a = (size_t)align; 23 | // Same as (p % a) but faster as 'a' is a power of two 24 | modulo = p & (a-1); 25 | 26 | if (modulo != 0) { 27 | // If 'p' address is not aligned, push the address to the 28 | // next value which is aligned 29 | p += a - modulo; 30 | } 31 | return p; 32 | } 33 | 34 | 35 | //~ Arena 36 | 37 | void* arena_alloc(M_Arena* arena, u64 size) { 38 | void* memory = 0; 39 | 40 | // align! 41 | size = align_forward_u64(size, DEFAULT_ALIGNMENT); 42 | 43 | if (arena->alloc_position + size > arena->commit_position) { 44 | if (!arena->static_size) { 45 | u64 commit_size = size; 46 | 47 | commit_size += M_ARENA_COMMIT_SIZE - 1; 48 | commit_size -= commit_size % M_ARENA_COMMIT_SIZE; 49 | 50 | if (arena->commit_position >= arena->max) { 51 | assert(0 && "Arena is out of memory"); 52 | } else { 53 | OS_MemoryCommit(arena->memory + arena->commit_position, commit_size); 54 | arena->commit_position += commit_size; 55 | } 56 | } else { 57 | assert(0 && "Static-Size Arena is out of memory"); 58 | } 59 | } 60 | 61 | memory = arena->memory + arena->alloc_position; 62 | arena->alloc_position += size; 63 | return memory; 64 | } 65 | 66 | void* arena_alloc_zero(M_Arena* arena, u64 size) { 67 | void* result = arena_alloc(arena, size); 68 | memset(result, 0, size); 69 | return result; 70 | } 71 | 72 | void arena_dealloc(M_Arena* arena, u64 size) { 73 | if (size > arena->alloc_position) 74 | size = arena->alloc_position; 75 | arena->alloc_position -= size; 76 | } 77 | 78 | void arena_dealloc_to(M_Arena* arena, u64 pos) { 79 | if (pos > arena->max) pos = arena->max; 80 | if (pos < 0) pos = 0; 81 | arena->alloc_position = pos; 82 | } 83 | 84 | void* arena_raise(M_Arena* arena, void* ptr, u64 size) { 85 | void* raised = arena_alloc(arena, size); 86 | memcpy(raised, ptr, size); 87 | return raised; 88 | } 89 | 90 | void* arena_alloc_array_sized(M_Arena* arena, u64 elem_size, u64 count) { 91 | return arena_alloc(arena, elem_size * count); 92 | } 93 | 94 | void arena_init(M_Arena* arena) { 95 | MemoryZeroStruct(arena, M_Arena); 96 | arena->max = M_ARENA_MAX; 97 | arena->memory = OS_MemoryReserve(arena->max); 98 | arena->alloc_position = 0; 99 | arena->commit_position = 0; 100 | arena->static_size = false; 101 | } 102 | 103 | void arena_init_sized(M_Arena* arena, u64 max) { 104 | MemoryZeroStruct(arena, M_Arena); 105 | arena->max = max; 106 | arena->memory = OS_MemoryReserve(arena->max); 107 | arena->alloc_position = 0; 108 | arena->commit_position = 0; 109 | arena->static_size = false; 110 | } 111 | 112 | void arena_clear(M_Arena* arena) { 113 | arena_dealloc(arena, arena->alloc_position); 114 | } 115 | 116 | void arena_free(M_Arena* arena) { 117 | OS_MemoryRelease(arena->memory, arena->max); 118 | } 119 | 120 | //~ Temp arena 121 | 122 | M_ArenaTemp arena_begin_temp(M_Arena* arena) { 123 | return (M_ArenaTemp) { arena, arena->alloc_position }; 124 | } 125 | 126 | void arena_end_temp(M_ArenaTemp temp) { 127 | arena_dealloc_to(temp.arena, temp.pos); 128 | } 129 | 130 | //~ Scratch Blocks 131 | 132 | M_Scratch scratch_get(void) { 133 | ThreadContext* ctx = (ThreadContext*) OS_ThreadContextGet(); 134 | return tctx_scratch_get(ctx); 135 | } 136 | 137 | void scratch_reset(M_Scratch* scratch) { 138 | ThreadContext* ctx = (ThreadContext*) OS_ThreadContextGet(); 139 | tctx_scratch_reset(ctx, scratch); 140 | } 141 | 142 | void scratch_return(M_Scratch* scratch) { 143 | ThreadContext* ctx = (ThreadContext*) OS_ThreadContextGet(); 144 | tctx_scratch_return(ctx, scratch); 145 | } 146 | 147 | //~ Pool 148 | 149 | void pool_init(M_Pool* pool, u64 element_size) { 150 | MemoryZeroStruct(pool, M_Pool); 151 | pool->memory = OS_MemoryReserve(M_POOL_MAX); 152 | pool->max = M_POOL_MAX; 153 | pool->commit_position = 0; 154 | pool->element_size = align_forward_u64(element_size, DEFAULT_ALIGNMENT); 155 | pool->head = nullptr; 156 | } 157 | 158 | void pool_clear(M_Pool* pool) { 159 | for (u8* it = (u8*)pool + sizeof(M_Pool), *preit = it; 160 | it <= (u8*)pool->memory + pool->commit_position; 161 | preit = it, it += pool->element_size) { 162 | ((M_PoolFreeNode*)preit)->next = (M_PoolFreeNode*)it; 163 | } 164 | pool->head = (M_PoolFreeNode*)pool->memory; 165 | } 166 | 167 | void pool_free(M_Pool* pool) { 168 | OS_MemoryRelease(pool->memory, pool->max); 169 | } 170 | 171 | void* pool_alloc(M_Pool* pool) { 172 | if (pool->head) { 173 | void* ret = pool->head; 174 | pool->head = pool->head->next; 175 | return ret; 176 | } else { 177 | if (pool->commit_position + M_POOL_COMMIT_CHUNK * pool->element_size >= pool->max) { 178 | assert(0 && "Pool is out of memory"); 179 | return nullptr; 180 | } 181 | void* commit_ptr = pool->memory + pool->commit_position; 182 | OS_MemoryCommit(commit_ptr, M_POOL_COMMIT_CHUNK * pool->element_size); 183 | pool_dealloc_range(pool, commit_ptr, M_POOL_COMMIT_CHUNK); 184 | 185 | pool->commit_position += M_POOL_COMMIT_CHUNK * pool->element_size; 186 | 187 | return pool_alloc(pool); 188 | } 189 | } 190 | 191 | void pool_dealloc(M_Pool* pool, void* ptr) { 192 | ((M_PoolFreeNode*)ptr)->next = pool->head; 193 | pool->head = ptr; 194 | } 195 | 196 | void pool_dealloc_range(M_Pool* pool, void* ptr, u64 count) { 197 | u8* it = ptr; 198 | for (u64 k = 0; k < count; k++) { 199 | ((M_PoolFreeNode*)it)->next = pool->head; 200 | pool->head = (M_PoolFreeNode*) it; 201 | it += pool->element_size; 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /source/base/mem.h: -------------------------------------------------------------------------------- 1 | /* date = September 27th 2021 11:45 am */ 2 | 3 | #ifndef MEM_H 4 | #define MEM_H 5 | 6 | #include 7 | #include "defines.h" 8 | 9 | //~ Arena (Linear Allocator) 10 | 11 | typedef struct M_Arena { 12 | u8* memory; 13 | u64 max; 14 | u64 alloc_position; 15 | u64 commit_position; 16 | b8 static_size; 17 | } M_Arena; 18 | 19 | #define M_ARENA_MAX Gigabytes(1) 20 | #define M_ARENA_COMMIT_SIZE Kilobytes(8) 21 | 22 | void* arena_alloc(M_Arena* arena, u64 size); 23 | void* arena_alloc_zero(M_Arena* arena, u64 size); 24 | void arena_dealloc(M_Arena* arena, u64 size); 25 | void arena_dealloc_to(M_Arena* arena, u64 pos); 26 | void* arena_raise(M_Arena* arena, void* ptr, u64 size); 27 | void* arena_alloc_array_sized(M_Arena* arena, u64 elem_size, u64 count); 28 | 29 | #define arena_alloc_array(arena, elem_type, count) \ 30 | arena_alloc_array_sized(arena, sizeof(elem_type), count) 31 | 32 | void arena_init(M_Arena* arena); 33 | void arena_init_sized(M_Arena* arena, u64 max); 34 | void arena_clear(M_Arena* arena); 35 | void arena_free(M_Arena* arena); 36 | 37 | typedef struct M_ArenaTemp { 38 | M_Arena* arena; 39 | u64 pos; 40 | } M_ArenaTemp; 41 | 42 | M_ArenaTemp arena_begin_temp(M_Arena* arena); 43 | void arena_end_temp(M_ArenaTemp temp); 44 | 45 | //~ Scratch Helpers 46 | // A scratch block is just a view into an arena 47 | #include "tctx.h" 48 | 49 | M_Scratch scratch_get(void); 50 | void scratch_reset(M_Scratch* scratch); 51 | void scratch_return(M_Scratch* scratch); 52 | 53 | //~ Pool (Pool Allocator) 54 | 55 | typedef struct M_PoolFreeNode M_PoolFreeNode; 56 | struct M_PoolFreeNode { M_PoolFreeNode* next; }; 57 | 58 | typedef struct M_Pool { 59 | u8* memory; 60 | u64 max; 61 | u64 commit_position; 62 | u64 element_size; 63 | 64 | M_PoolFreeNode* head; 65 | } M_Pool; 66 | 67 | #define M_POOL_MAX Gigabytes(1) 68 | #define M_POOL_COMMIT_CHUNK 32 69 | 70 | void pool_init(M_Pool* pool, u64 element_size); 71 | void pool_clear(M_Pool* pool); 72 | void pool_free(M_Pool* pool); 73 | 74 | void* pool_alloc(M_Pool* pool); 75 | void pool_dealloc(M_Pool* pool, void* ptr); 76 | void pool_dealloc_range(M_Pool* pool, void* ptr, u64 count); 77 | 78 | #endif //MEM_H -------------------------------------------------------------------------------- /source/base/str.h: -------------------------------------------------------------------------------- 1 | /* date = September 27th 2021 3:04 pm */ 2 | 3 | #ifndef STR_H 4 | #define STR_H 5 | 6 | #include 7 | #include "mem.h" 8 | 9 | typedef struct string_const { 10 | u8* str; 11 | u64 size; 12 | } string_const; 13 | typedef string_const string; 14 | 15 | typedef struct string_const_list_node { 16 | string str; 17 | struct string_const_list_node* next; 18 | } string_const_list_node; 19 | typedef string_const_list_node string_list_node; 20 | 21 | typedef struct string_const_list { 22 | string_const_list_node* first; 23 | string_const_list_node* last; 24 | i32 node_count; 25 | u64 total_size; 26 | } string_const_list; 27 | typedef string_const_list string_list; 28 | 29 | typedef struct string_const_array { 30 | u32 cap; 31 | u32 len; 32 | string* elems; 33 | } string_const_array; 34 | typedef string_const_array string_array; 35 | 36 | void string_array_add(string_const_array* array, string data); 37 | string_const string_array_remove(string_const_array* array, int idx); 38 | void string_array_free(string_const_array* array); 39 | 40 | //- 41 | 42 | #define str_lit(s) (string_const) { .str = (u8*)(s), .size = sizeof(s) - 1 } 43 | #define str_make(s) (string_const) { .str = (u8*)(s), .size = strlen(s) } 44 | #define str_expand(s) (i32)(s).size, (s).str 45 | 46 | string_const str_alloc(M_Arena* arena, u64 size); // NOTE(EVERYONE): this will try to get one extra byte for \0 47 | string_const str_copy(M_Arena* arena, string_const other); 48 | string_const str_cat(M_Arena* arena, string_const a, string_const b); 49 | string_const str_from_format(M_Arena* arena, const char* format, ...); 50 | string_const str_replace_all(M_Arena* arena, string_const to_fix, string_const needle, string_const replacement); 51 | u64 str_substr_count(string_const str, string_const needle); 52 | u64 str_find_first(string_const str, string_const needle, u32 offset); 53 | u64 str_find_last(string_const str, string_const needle, u32 offset); 54 | u32 str_hash(string_const str); 55 | u64 str_hash_64(string_const str); 56 | 57 | b8 str_eq(string_const a, string_const b); 58 | b8 str_is_null(string k); 59 | 60 | void string_list_push_node(string_const_list* list, string_const_list_node* node); 61 | void string_list_push(M_Arena* arena, string_const_list* list, string_const str); 62 | b8 string_list_equals(string_const_list* a, string_const_list* b); 63 | b8 string_list_contains(string_const_list* a, string_const needle); 64 | string_const string_list_flatten(M_Arena* arena, string_const_list* list); 65 | 66 | //- Encoding Stuff 67 | 68 | typedef struct string_utf16_const { 69 | u16* str; 70 | u64 size; 71 | } string_utf16_const; 72 | typedef string_utf16_const string_utf16; 73 | 74 | string_utf16_const str16_cstring(u16 *cstr); 75 | string_utf16_const str16_from_str8(M_Arena *arena, string_const str); 76 | string_const str8_from_str16(M_Arena *arena, string_utf16_const str); 77 | 78 | #endif //STR_H 79 | -------------------------------------------------------------------------------- /source/base/tctx.c: -------------------------------------------------------------------------------- 1 | #include "mem.h" 2 | // Dependency on the OS. Although it is generic 3 | #include "os/os.h" 4 | 5 | void tctx_init(ThreadContext* ctx) { 6 | arena_init(&ctx->arena); 7 | OS_ThreadContextSet(ctx); 8 | } 9 | 10 | void tctx_free(ThreadContext* ctx) { 11 | arena_free(&ctx->arena); 12 | OS_ThreadContextSet(ctx); 13 | } 14 | 15 | M_Scratch tctx_scratch_get(ThreadContext* ctx) { 16 | if (!ctx->free_list) { 17 | M_Scratch scratch = {0}; 18 | 19 | void* ptr = arena_alloc(&ctx->arena, M_SCRATCH_SIZE); 20 | scratch.arena.memory = ptr; 21 | scratch.arena.max = M_SCRATCH_SIZE; 22 | scratch.arena.alloc_position = 0; 23 | scratch.arena.commit_position = M_SCRATCH_SIZE; 24 | scratch.arena.static_size = true; 25 | 26 | ctx->max_created++; 27 | return scratch; 28 | } else { 29 | M_Scratch scratch = {0}; 30 | 31 | scratch.arena.memory = (u8*) ctx->free_list; 32 | scratch.arena.max = M_SCRATCH_SIZE; 33 | scratch.arena.alloc_position = 0; 34 | scratch.arena.commit_position = M_SCRATCH_SIZE; 35 | scratch.arena.static_size = true; 36 | 37 | ctx->free_list = ctx->free_list->next; 38 | return scratch; 39 | } 40 | } 41 | 42 | void tctx_scratch_reset(ThreadContext* ctx, M_Scratch* scratch) { 43 | scratch->arena.alloc_position = 0; 44 | } 45 | 46 | void tctx_scratch_return(ThreadContext* ctx, M_Scratch* scratch) { 47 | scratch_free_list_node* prev_head = ctx->free_list; 48 | ctx->free_list = (scratch_free_list_node*) scratch->arena.memory; 49 | ctx->free_list->next = prev_head; 50 | } 51 | -------------------------------------------------------------------------------- /source/base/tctx.h: -------------------------------------------------------------------------------- 1 | /* date = June 30th 2022 0:24 pm */ 2 | 3 | #ifndef TCTX_H 4 | #define TCTX_H 5 | 6 | #include "defines.h" 7 | 8 | #define M_SCRATCH_SIZE Kilobytes(16) 9 | typedef struct scratch_free_list_node scratch_free_list_node; 10 | struct scratch_free_list_node { 11 | scratch_free_list_node* next; 12 | u32 index; 13 | }; 14 | 15 | typedef struct M_Scratch { 16 | M_Arena arena; 17 | u32 index; 18 | u64 pos; 19 | } M_Scratch; 20 | 21 | typedef struct ThreadContext { 22 | M_Arena arena; 23 | u32 max_created; 24 | scratch_free_list_node* free_list; 25 | } ThreadContext; 26 | 27 | void tctx_init(ThreadContext* ctx); 28 | void tctx_free(ThreadContext* ctx); 29 | 30 | M_Scratch tctx_scratch_get(ThreadContext* ctx); 31 | void tctx_scratch_reset(ThreadContext* ctx, M_Scratch* scratch); 32 | void tctx_scratch_return(ThreadContext* ctx, M_Scratch* scratch); 33 | 34 | #endif //TCTX_H 35 | -------------------------------------------------------------------------------- /source/base/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | 6 | //~ Time 7 | 8 | U_DenseTime U_DenseTimeFromDateTime(U_DateTime* datetime) { 9 | u32 encoded = (u32)((s32)datetime->year + 0x8000); 10 | U_DenseTime result = 0; 11 | result += encoded; 12 | result *= 12; 13 | result += datetime->month; 14 | result *= 31; 15 | result += datetime->day; 16 | result *= 24; 17 | result += datetime->hour; 18 | result *= 60; 19 | result += datetime->minute; 20 | result *= 60; 21 | result += datetime->sec; 22 | result *= 1000; 23 | result += datetime->ms; 24 | return result; 25 | } 26 | 27 | U_DateTime U_DateTimeFromDenseTime(U_DenseTime densetime) { 28 | U_DateTime result = {0}; 29 | result.ms = densetime % 1000; 30 | densetime /= 1000; 31 | result.sec = densetime % 60; 32 | densetime /= 60; 33 | result.minute = densetime % 60; 34 | densetime /= 60; 35 | result.hour = densetime % 24; 36 | densetime /= 24; 37 | result.day = densetime % 31; 38 | densetime /= 31; 39 | result.month = densetime % 12; 40 | densetime /= 12; 41 | result.year = ((s32)densetime) - 0x8000; 42 | return result; 43 | } 44 | 45 | //~ Time 46 | 47 | string U_FixFilepath(M_Arena* arena, string filepath) { 48 | M_Scratch scratch = scratch_get(); 49 | 50 | string fixed = filepath; 51 | fixed = str_replace_all(&scratch.arena, fixed, str_lit("\\"), str_lit("/")); 52 | fixed = str_replace_all(arena, fixed, str_lit("/./"), str_lit("/")); 53 | while (true) { 54 | u64 dotdot = str_find_first(fixed, str_lit(".."), 0); 55 | if (dotdot == fixed.size) break; 56 | 57 | u64 last_slash = str_find_last(fixed, str_lit("/"), dotdot - 1); 58 | 59 | u64 range = (dotdot + 3) - last_slash; 60 | string old = fixed; 61 | fixed = str_alloc(&scratch.arena, fixed.size - range); 62 | memcpy(fixed.str, old.str, last_slash); 63 | memcpy(fixed.str + last_slash, old.str + dotdot + 3, old.size - range - last_slash + 1); 64 | } 65 | 66 | fixed = str_copy(arena, fixed); 67 | scratch_return(&scratch); 68 | 69 | return fixed; 70 | } 71 | 72 | string U_GetFullFilepath(M_Arena* arena, string filename) { 73 | M_Scratch scratch = scratch_get(); 74 | 75 | char buffer[PATH_MAX]; 76 | get_cwd(buffer, PATH_MAX); 77 | string cwd = { .str = (u8*) buffer, .size = strlen(buffer) }; 78 | 79 | string finalized = str_cat(&scratch.arena, cwd, str_lit("/")); 80 | finalized = str_cat(&scratch.arena, finalized, filename); 81 | finalized = U_FixFilepath(arena, finalized); 82 | 83 | scratch_return(&scratch); 84 | return finalized; 85 | } 86 | 87 | string U_GetFilenameFromFilepath(string filepath) { 88 | u64 last_slash = str_find_last(filepath, str_lit("/"), 0); 89 | 90 | if (last_slash == filepath.size) 91 | last_slash = 0; 92 | else if (last_slash == 0) 93 | last_slash = str_find_last(filepath, str_lit("\\"), 0); 94 | 95 | u64 sizeof_filename = filepath.size - last_slash; 96 | return (string) { .str = filepath.str + last_slash, .size = sizeof_filename }; 97 | } 98 | 99 | string U_GetDirectoryFromFilepath(string filepath) { 100 | u64 last_slash = str_find_last(filepath, str_lit("/"), 0); 101 | if (last_slash == 0) last_slash = str_find_last(filepath, str_lit("\\"), 0); 102 | return (string) { .str = filepath.str, .size = last_slash - 1 }; 103 | } 104 | 105 | //~ Frame Arena 106 | 107 | // Just a global. Maybe should be a thread local but /shrug 108 | M_Arena frame_arena; 109 | 110 | void U_FrameArenaInit(void) { 111 | arena_init(&frame_arena); 112 | } 113 | 114 | void U_FrameArenaFree(void) { 115 | arena_free(&frame_arena); 116 | } 117 | 118 | M_Arena* U_GetFrameArena(void) { 119 | return &frame_arena; 120 | } 121 | 122 | void U_ResetFrameArena(void) { 123 | arena_dealloc_to(&frame_arena, 0); 124 | } 125 | 126 | -------------------------------------------------------------------------------- /source/base/utils.h: -------------------------------------------------------------------------------- 1 | /* date = March 11th 2022 2:07 pm */ 2 | 3 | #ifndef UTILS_H 4 | #define UTILS_H 5 | 6 | #include "defines.h" 7 | #include "mem.h" 8 | #include "str.h" 9 | 10 | //~ Time 11 | 12 | typedef u64 U_DenseTime; 13 | 14 | typedef struct U_DateTime { 15 | u16 ms; 16 | u8 sec; 17 | u8 minute; 18 | u8 hour; 19 | u8 day; 20 | u8 month; 21 | s32 year; 22 | } U_DateTime; 23 | 24 | U_DenseTime U_DenseTimeFromDateTime(U_DateTime* datetime); 25 | U_DateTime U_DateTimeFromDenseTime(U_DenseTime densetime); 26 | 27 | //~ Filepaths 28 | 29 | string U_FixFilepath(M_Arena* arena, string filepath); 30 | string U_GetFullFilepath(M_Arena* arena, string filename); 31 | string U_GetFilenameFromFilepath(string filepath); 32 | string U_GetDirectoryFromFilepath(string filepath); 33 | 34 | //~ Frame Arena 35 | // This is an arena simply useful for one frame 36 | 37 | void U_FrameArenaInit(void); 38 | void U_FrameArenaFree(void); 39 | M_Arena* U_GetFrameArena(void); 40 | void U_ResetFrameArena(void); 41 | 42 | #endif //UTILS_H 43 | -------------------------------------------------------------------------------- /source/base/vmath.c: -------------------------------------------------------------------------------- 1 | #include "vmath.h" 2 | 3 | #include 4 | 5 | void animate_f32exp(f32* val, f32 target, f32 speed, f32 dt) { 6 | f32 delta = target - (*val); 7 | *val += delta * dt * speed; 8 | } 9 | 10 | vec2 vec2_triple_product(vec2 a, vec2 b, vec2 c) { 11 | vec3 p = vec3_cross((vec3) { b.x, b.y, 0.0 }, (vec3) { c.x, c.y, 0.0 }); 12 | vec3 q = vec3_cross((vec3) { a.x, a.y, 0.0 }, p); 13 | return (vec2) { q.x, q.y }; 14 | } 15 | 16 | vec2 vec2_clamp(vec2 vec, rect quad) { 17 | return (vec2) { 18 | .x = Clamp(quad.x, vec.x, quad.x + quad.w), 19 | .y = Clamp(quad.y, vec.y, quad.y + quad.h) 20 | }; 21 | } 22 | 23 | vec3 vec3_mul(vec3 a, mat3 m) { 24 | return (vec3) { 25 | .x = (a.x * m.a[mat3_idx(0, 0)] + a.y * m.a[mat3_idx(1, 0)] + a.z * m.a[mat3_idx(2, 0)]), 26 | .y = (a.x * m.a[mat3_idx(0, 1)] + a.y * m.a[mat3_idx(1, 1)] + a.z * m.a[mat3_idx(2, 1)]), 27 | .z = (a.x * m.a[mat3_idx(0, 2)] + a.y * m.a[mat3_idx(1, 2)] + a.z * m.a[mat3_idx(2, 2)]) 28 | }; 29 | } 30 | 31 | vec4 vec4_mul(vec4 a, mat4 m) { 32 | return (vec4) { 33 | .x = (a.x * m.a[mat4_idx(0, 0)] + a.y * m.a[mat4_idx(1, 0)] + a.z * m.a[mat4_idx(2, 0)] + a.w * m.a[mat4_idx(3, 0)]), 34 | .y = (a.x * m.a[mat4_idx(0, 1)] + a.y * m.a[mat4_idx(1, 1)] + a.z * m.a[mat4_idx(2, 1)] + a.w * m.a[mat4_idx(3, 1)]), 35 | .z = (a.x * m.a[mat4_idx(0, 2)] + a.y * m.a[mat4_idx(1, 2)] + a.z * m.a[mat4_idx(2, 2)] + a.w * m.a[mat4_idx(3, 2)]), 36 | .w = (a.x * m.a[mat4_idx(0, 3)] + a.y * m.a[mat4_idx(1, 3)] + a.z * m.a[mat4_idx(2, 3)] + a.w * m.a[mat4_idx(3, 3)]) 37 | }; 38 | } 39 | 40 | mat3 mat3_identity() { 41 | return (mat3) { 42 | .a = { 43 | 1.f, 0.f, 0.f, 44 | 0.f, 1.f, 0.f, 45 | 0.f, 0.f, 1.f, 46 | } 47 | }; 48 | } 49 | 50 | mat4 mat4_identity() { 51 | return (mat4) { 52 | .a = { 53 | 1.f, 0.f, 0.f, 0.f, 54 | 0.f, 1.f, 0.f, 0.f, 55 | 0.f, 0.f, 1.f, 0.f, 56 | 0.f, 0.f, 0.f, 1.f, 57 | } 58 | }; 59 | } 60 | 61 | mat3 mat3_mul(mat3 a, mat3 b) { 62 | mat3 result = mat3_identity(); 63 | for (u16 j = 0; j < 3; j++) { 64 | for (u16 i = 0; i < 3; i++) { 65 | result.a[mat3_idx(i, j)] = 66 | a.a[mat3_idx(i, 0)] * b.a[mat3_idx(0, j)] + 67 | a.a[mat3_idx(i, 1)] * b.a[mat3_idx(1, j)] + 68 | a.a[mat3_idx(i, 2)] * b.a[mat3_idx(2, j)]; 69 | } 70 | } 71 | return result; 72 | } 73 | 74 | void mat3_set(mat3* mat, mat3 o) { 75 | for (u16 j = 0; j < 3; j++) { 76 | for (u16 i = 0; i < 3; i++) { 77 | mat->a[mat3_idx(i, j)] = o.a[mat3_idx(i, j)]; 78 | } 79 | } 80 | } 81 | 82 | mat3 mat3_translate(vec2 v) { 83 | return (mat3) { 84 | .a = { 85 | 1.f, 0.f, v.x, 86 | 0.f, 1.f, v.y, 87 | 0.f, 0.f, 1.f, 88 | } 89 | }; 90 | } 91 | 92 | mat3 mat3_rotate(f32 r) { 93 | return (mat3) { 94 | .a = { 95 | cos(radians(r)), -sin(radians(r)), 0.f, 96 | sin(radians(r)), cos(radians(r)), 0.f, 97 | 0.f, 0.f, 1.f, 98 | } 99 | }; 100 | } 101 | 102 | mat3 mat3_scalev(vec2 s) { 103 | return (mat3) { 104 | .a = { 105 | s.x, 0.f, 0.f, 106 | 0.f, s.y, 0.f, 107 | 0.f, 0.f, 1.f, 108 | } 109 | }; 110 | } 111 | 112 | mat3 mat3_scalef(f32 s) { 113 | return (mat3) { 114 | .a = { 115 | s, 0.f, 0.f, 116 | 0.f, s, 0.f, 117 | 0.f, 0.f, 1.f, 118 | } 119 | }; 120 | } 121 | 122 | mat4 mat4_mul(mat4 a, mat4 b) { 123 | mat4 result = mat4_identity(); 124 | for (u16 j = 0; j < 4; j++) { 125 | for (u16 i = 0; i < 4; i++) { 126 | result.a[mat4_idx(i, j)] = 127 | a.a[mat4_idx(i, 0)] * b.a[mat4_idx(0, j)] + 128 | a.a[mat4_idx(i, 1)] * b.a[mat4_idx(1, j)] + 129 | a.a[mat4_idx(i, 2)] * b.a[mat4_idx(2, j)] + 130 | a.a[mat4_idx(i, 3)] * b.a[mat4_idx(3, j)]; 131 | } 132 | } 133 | return result; 134 | } 135 | 136 | void mat4_set(mat4* mat, mat4 o) { 137 | for (u16 j = 0; j < 4; j++) { 138 | for (u16 i = 0; i < 4; i++) { 139 | mat->a[mat4_idx(i, j)] = o.a[mat4_idx(i, j)]; 140 | } 141 | } 142 | } 143 | 144 | mat4 mat4_translate(vec3 v) { 145 | return (mat4) { 146 | .a = { 147 | 1.f, 0.f, 0.f, v.x, 148 | 0.f, 1.f, 0.f, v.y, 149 | 0.f, 0.f, 1.f, v.z, 150 | 0.f, 0.f, 0.f, 1.f, 151 | } 152 | }; 153 | } 154 | 155 | mat4 mat4_scale(vec3 v) { 156 | return (mat4) { 157 | .a = { 158 | v.x, 0.f, 0.f, 0.f, 159 | 0.f, v.y, 0.f, 0.f, 160 | 0.f, 0.f, v.z, 0.f, 161 | 0.f, 0.f, 0.f, 1.f, 162 | } 163 | }; 164 | } 165 | 166 | mat4 mat4_rotX(f32 deg) { 167 | f64 rad = deg * DEG_TO_RAD; 168 | return (mat4) { 169 | .a = { 170 | 1.f, 0.f, 0.f, 0.f, 171 | 0.f, cosf(rad), -sinf(rad), 0.f, 172 | 0.f, sinf(rad), cosf(rad), 0.f, 173 | 0.f, 0.f, 0.f, 1.f, 174 | } 175 | }; 176 | } 177 | 178 | mat4 mat4_rotY(f32 deg) { 179 | f64 rad = deg * DEG_TO_RAD; 180 | return (mat4) { 181 | .a = { 182 | cosf(rad), 0.f, -sinf(rad), 0.f, 183 | 0.f, 1.f, 0.f, 0.f, 184 | sinf(rad), 0.f, cosf(rad), 0.f, 185 | 0.f, 0.f, 0.f, 1.f, 186 | } 187 | }; 188 | } 189 | 190 | mat4 mat4_rotZ(f32 deg) { 191 | f64 rad = deg * DEG_TO_RAD; 192 | return (mat4) { 193 | .a = { 194 | cosf(rad), -sinf(rad), 0.f, 0.f, 195 | sinf(rad), cosf(rad), 0.f, 0.f, 196 | 0.f, 0.f, 1.f, 0.f, 197 | 0.f, 0.f, 0.f, 1.f, 198 | } 199 | }; 200 | } 201 | 202 | mat4 mat4_transpose(mat4 a) { 203 | mat4 ret = mat4_identity(); 204 | for (u16 j = 0; j < 4; j++) { 205 | for (u16 i = 0; i < 4; i++) { 206 | ret.a[mat4_idx(i, j)] = a.a[mat4_idx(j, i)]; 207 | } 208 | } 209 | return ret; 210 | } 211 | 212 | mat4 mat4_ortho(f32 left, f32 right, f32 top, f32 bottom, f32 near, f32 far) { 213 | f32 width = right - left; 214 | f32 height = top - bottom; 215 | f32 depth = far - near; 216 | return (mat4) { 217 | .a = { 218 | 2.f / width, 0.f, 0.f, 0.f, 219 | 0.f, 2.f / height, 0.f, 0.f, 220 | 0.f, 0.f, -2.f / depth, 0.f, 221 | -(right + left) / width, -(top + bottom) / height, -(far + near) / depth, 1.f, 222 | } 223 | }; 224 | } 225 | 226 | mat4 mat4_perspective(f32 fov, f32 aspect_ratio, f32 near, f32 far) { 227 | f32 top = tanf(fov * DEG_TO_RAD / 2) * near; 228 | f32 right = top * aspect_ratio; 229 | f32 depth = far - near; 230 | return (mat4) { 231 | .a = { 232 | 1.f / right, 0.f, 0.f, 0.f, 233 | 0.f, 1.f / top, 0.f, 0.f, 234 | 0.f, 0.f, -2.f / depth, 0.f, 235 | 0.f, 0.f, -(far + near) / depth, 1.f, 236 | } 237 | }; 238 | } 239 | 240 | quat quat_identity() { 241 | return (quat) { 1, 0, 0, 0 }; 242 | } 243 | 244 | quat quat_mul(quat a, quat b) { 245 | return (quat) { 246 | a.s * b.s - a.i * b.i - a.j * b.j - a.k * b.k, 247 | a.s * b.i + a.i * b.s + a.j * b.k + a.k * b.j, 248 | a.s * b.j + a.j * b.s + a.i * b.k + a.k * b.i, 249 | a.s * b.k + a.k * b.s + a.i * b.j + a.j * b.i 250 | }; 251 | } 252 | 253 | f32 quat_length(quat q) { 254 | return sqrtf(q.s * q.s + q.i * q.i + q.j * q.j + q.k * q.k); 255 | } 256 | 257 | quat quat_norm(quat q) { 258 | f32 len = quat_length(q); 259 | return (quat) { q.s / len, q.i / len, q.j / len, q.k / len }; 260 | } 261 | 262 | quat quat_rotate_axis(quat q, f32 x, f32 y, f32 z, f32 a) { 263 | f32 factor = sinf(a / 2.0f); 264 | 265 | quat r = {0}; 266 | r.i = x * factor; 267 | r.j = y * factor; 268 | r.k = z * factor; 269 | r.s = cosf(a / 2.0f); 270 | 271 | return quat_norm(r); 272 | } 273 | 274 | quat quat_from_euler(f32 yaw, f32 pitch, f32 roll) { 275 | // Abbreviations for the various angular functions 276 | f32 cy = cosf(yaw * 0.5); 277 | f32 sy = sinf(yaw * 0.5); 278 | f32 cp = cosf(pitch * 0.5); 279 | f32 sp = sinf(pitch * 0.5); 280 | f32 cr = cosf(roll * 0.5); 281 | f32 sr = sinf(roll * 0.5); 282 | 283 | quat q; 284 | q.s = cr * cp * cy + sr * sp * sy; 285 | q.i = sr * cp * cy - cr * sp * sy; 286 | q.j = cr * sp * cy + sr * cp * sy; 287 | q.k = cr * cp * sy - sr * sp * cy; 288 | return q; 289 | } 290 | 291 | mat4 quat_to_rotation_mat(quat q) { 292 | f32 isq = q.i * q.i; 293 | f32 jsq = q.j * q.j; 294 | f32 ksq = q.k * q.k; 295 | 296 | return (mat4) { 297 | .a = { 298 | 1 - 2*jsq - 2*ksq, 2*q.i*q.j - 2*q.s*q.k, 2*q.i*q.k + 2*q.s*q.j, 0, 299 | 2*q.i*q.j + 2*q.s*q.k, 1 - 2*isq - 2*ksq, 2*q.j*q.k - 2*q.s*q.i, 0, 300 | 2*q.i*q.k - 2*q.s*q.j, 2*q.j*q.k + 2*q.s*q.i, 1 - 2*isq - 2*jsq, 0, 301 | 0, 0, 0, 1 302 | } 303 | }; 304 | } 305 | 306 | 307 | b8 rect_contains_point(rect a, vec2 p) { 308 | return a.x <= p.x && a.y <= p.y && a.x + a.w >= p.x && a.y + a.h >= p.y; 309 | } 310 | 311 | b8 rect_overlaps(rect a, rect b) { 312 | b8 x = (a.x >= b.x && a.x <= b.x + b.w) || (a.x + a.w >= b.x && a.x + a.w <= b.x + b.w) || (a.x <= b.x && a.x + a.w >= b.x + b.w); 313 | b8 y = (a.y >= b.y && a.y <= b.y + b.h) || (a.y + a.h >= b.y && a.y + a.h <= b.y + b.h) || (a.y <= b.y && a.y + a.h >= b.y + b.h); 314 | return x && y; 315 | } 316 | 317 | b8 rect_contained_by_rect(rect a, rect b) { 318 | b8 x = (a.x >= b.x && a.x <= b.x + b.w) && (a.x + a.w >= b.x && a.x + a.w <= b.x + b.w); 319 | b8 y = (a.y >= b.y && a.y <= b.y + b.h) && (a.y + a.h >= b.y && a.y + a.h <= b.y + b.h); 320 | return x && y; 321 | } 322 | 323 | rect rect_get_overlap(rect a, rect b) { 324 | vec2 min = (vec2) { Max(a.x, b.x), Max(a.y, b.y) }; 325 | vec2 max = (vec2) { Min(a.x + a.w, b.x + b.w), Min(a.y + a.h, b.y + b.h) }; 326 | return (rect) { min.x, min.y, max.x - min.x, max.y - min.y, }; 327 | } 328 | 329 | rect rect_uv_cull(rect quad, rect uv, rect cull_quad) { 330 | if (!rect_overlaps(quad, cull_quad) || rect_contained_by_rect(quad, cull_quad)) { 331 | return uv; 332 | } 333 | 334 | b8 x_shift_constant = !(quad.x >= cull_quad.x && quad.x <= cull_quad.x + cull_quad.w); 335 | b8 y_shift_constant = !(quad.y >= cull_quad.y && quad.y <= cull_quad.y + cull_quad.h); 336 | 337 | f32 uv_xratio = uv.w / quad.w; 338 | f32 uv_yratio = uv.h / quad.h; 339 | rect overlap = rect_get_overlap(quad, cull_quad); 340 | f32 culled_x = uv.x + (quad.w - overlap.w) * uv_xratio * x_shift_constant; 341 | f32 culled_y = uv.y + (quad.h - overlap.h) * uv_yratio * y_shift_constant; 342 | f32 culled_w = overlap.w * uv_xratio; 343 | f32 culled_h = overlap.h * uv_yratio; 344 | return (rect) { culled_x, culled_y, culled_w, culled_h }; 345 | } 346 | -------------------------------------------------------------------------------- /source/base/vmath.h: -------------------------------------------------------------------------------- 1 | /* date = September 29th 2021 10:03 am */ 2 | 3 | #ifndef VMATH_H 4 | #define VMATH_H 5 | 6 | #include "defines.h" 7 | #include 8 | 9 | //~ Constants and Defines 10 | 11 | #define EPSILON 0.001f 12 | #define PI 3.141592653589f 13 | #define PHI 1.61803399f 14 | #define HALF_PI 1.570796326794f 15 | #define DEG_TO_RAD 0.0174532925f 16 | #define RAD_TO_DEG 57.2957795131 17 | #define FLOAT_MAX 340282346638528859811704183484516925440.0000000000000000 18 | #define FLOAT_MIN -FLOAT_MAX 19 | 20 | #define EpsilonEquals(x, y) ((fabs((x) - (y)) <= EPSILON) ? true : false) 21 | 22 | //~ Linear algebra 23 | 24 | typedef struct vec2 { f32 x; f32 y; } vec2; 25 | typedef struct vec3 { f32 x; f32 y; f32 z; } vec3; 26 | typedef struct vec4 { f32 x; f32 y; f32 z; f32 w; } vec4; 27 | 28 | typedef struct mat3 { f32 a[3*3]; } mat3; 29 | typedef struct mat4 { f32 a[4*4]; } mat4; 30 | 31 | typedef struct rect { f32 x; f32 y; f32 w; f32 h; } rect; 32 | typedef struct quat { f32 s; f32 i; f32 j; f32 k; } quat; 33 | 34 | //~ Helpful Color things 35 | 36 | #define Color_Red vec4_init(0.8f, 0.2f, 0.3f, 1.f) 37 | #define Color_Green vec4_init(0.2f, 0.8f, 0.3f, 1.f) 38 | #define Color_Blue vec4_init(0.3f, 0.2f, 0.8f, 1.f) 39 | #define Color_Magenta vec4_init(0.8f, 0.3f, 0.7f, 1.f) 40 | #define Color_Cyan vec4_init(0.3f, 0.8f, 0.7f, 1.f) 41 | #define Color_Yellow vec4_init(0.8f, 0.7f, 0.3f, 1.f) 42 | #define Color_PureRed vec4_init(1.0f, 0.0f, 0.0f, 1.f) 43 | #define Color_PureGreen vec4_init(0.0f, 1.0f, 0.0f, 1.f) 44 | #define Color_PureBlue vec4_init(0.0f, 0.0f, 1.0f, 1.f) 45 | #define Color_White vec4_init(1.0f, 1.0f, 1.0f, 1.f) 46 | 47 | #define ColorCode_Red 0xCC4D33FF 48 | #define ColorCode_Green 0x33CC4DFF 49 | #define ColorCode_Blue 0x4D33CCFF 50 | #define ColorCode_Magenta 0xCC4DB1FF 51 | #define ColorCode_Purple 0x8B46B3FF 52 | #define ColorCode_Cyan 0x4DCCB1FF 53 | #define ColorCode_Yellow 0xCCB14DFF 54 | #define ColorCode_PureRed 0xFF0000FF 55 | #define ColorCode_PureGreen 0x00FF00FF 56 | #define ColorCode_PureBlue 0x0000FFFF 57 | #define ColorCode_White 0xFFFFFFFF 58 | 59 | static inline vec4 color_code_to_vec4(u32 code) { 60 | return (vec4) { .x=((code >> 24)&0xFF)/255.f, .y=((code>>16)&0xFF)/255.f, .z=((code>>8)&0xFF)/255.f, .w=(code&0xFF)/255.f }; 61 | } 62 | 63 | //~ Math Utilities 64 | 65 | void animate_f32exp(f32* val, f32 target, f32 speed, f32 dt); 66 | 67 | typedef u32 axis2; 68 | enum { 69 | axis2_x, 70 | axis2_y, 71 | axis2_count, 72 | }; 73 | 74 | typedef u32 axis3; 75 | enum { 76 | axis3_x, 77 | axis3_y, 78 | axis3_z, 79 | axis3_count, 80 | }; 81 | 82 | //~ Inline Initializers 83 | 84 | #define v2(x, y) ((vec2) { (x), (y) }) 85 | #define v3(x, y, z) ((vec3) { (x), (y), (z) }) 86 | #define v4(x, y, z, w) ((vec4) { (x), (y), (z), (w) }) 87 | 88 | static inline vec2 vec2_init(f32 x, f32 y) { return (vec2) { x, y }; } 89 | static inline vec3 vec3_init(f32 x, f32 y, f32 z) { return (vec3) { x, y, z }; } 90 | static inline vec4 vec4_init(f32 x, f32 y, f32 z, f32 w) { return (vec4) { x, y, z, w }; } 91 | static inline rect rect_init(f32 x, f32 y, f32 w, f32 h) { return (rect) { x, y, w, h }; } 92 | static inline quat quat_init(f32 s, f32 i, f32 j, f32 k) { return (quat) { s, i, j, k }; } 93 | 94 | static inline u16 mat3_idx(u16 x, u16 y) { return y * 3 + x; } 95 | static inline u16 mat4_idx(u16 x, u16 y) { return y * 4 + x; } 96 | 97 | static inline f64 radians(f32 deg) { return (f64) (deg * DEG_TO_RAD); } 98 | static inline f32 degrees(f64 rad) { return (f32) (rad * RAD_TO_DEG); } 99 | static inline f32 lerp(f32 a, f32 b, f32 t) { return a * (1-t) + b * t; } 100 | 101 | //~ Vector Functions 102 | 103 | static inline vec2 vec2_add(vec2 a, vec2 b) { return (vec2) { .x = a.x + b.x, .y = a.y + b.y }; } 104 | static inline vec2 vec2_sub(vec2 a, vec2 b) { return (vec2) { .x = a.x - b.x, .y = a.y - b.y }; } 105 | static inline vec2 vec2_scale(vec2 a, f32 s) { return (vec2) { .x = a.x * s, .y = a.y * s }; } 106 | static inline f32 vec2_mag(vec2 v) { return sqrtf(v.x * v.x + v.y * v.y); } 107 | static inline f32 vec2_magsq(vec2 v) { return v.x * v.x + v.y * v.y; } 108 | static inline vec2 vec2_normalize(vec2 v) { return vec2_scale(v, 1.f / vec2_mag(v)); } 109 | static inline vec2 vec2_neg(vec2 v) { return (vec2) { .x = -v.x, .y = -v.y }; } 110 | static inline f32 vec2_dot(vec2 a, vec2 b) { return a.x * b.x + a.y * b.y; } 111 | vec2 vec2_triple_product(vec2 a, vec2 b, vec2 c); 112 | vec2 vec2_clamp(vec2 vec, rect quad); 113 | 114 | static inline 115 | vec3 vec3_add(vec3 a, vec3 b) { return (vec3) { .x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z }; } 116 | static inline 117 | vec3 vec3_sub(vec3 a, vec3 b) { return (vec3) { .x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z }; } 118 | static inline 119 | vec3 vec3_scale(vec3 a, f32 s) { return (vec3) { .x = a.x * s, .y = a.y * s, .z = a.z * s }; } 120 | static inline 121 | vec3 vec3_cross(vec3 a, vec3 b) { return (vec3) { .x = a.y * b.z - b.y * a.z, .y = a.x * b.z - b.x * a.z, .z = a.x * b.y + b.x * a.y }; } 122 | 123 | static inline 124 | vec4 vec4_add(vec4 a, vec4 b) { return (vec4) { .x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z, .w = a.w + b.w }; } 125 | static inline 126 | vec4 vec4_sub(vec4 a, vec4 b) { return (vec4) { .x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z, .w = a.w - b.w }; } 127 | static inline 128 | vec4 vec4_scale(vec4 a, f32 s) { return (vec4) { .x = a.x * s, .y = a.y * s, .z = a.z * s, .w = a.w * s }; } 129 | static inline 130 | vec4 vec4_lerp(vec4 a, vec4 b, f32 t) { return (vec4) { lerp(a.x, b.x, t), lerp(a.y, b.y, t), lerp(a.z, b.z, t), lerp(a.w, b.w, t) }; } 131 | 132 | vec3 vec3_mul(vec3 a, mat3 m); 133 | vec4 vec4_mul(vec4 a, mat4 m); 134 | 135 | //~ Matrix Functions 136 | 137 | mat3 mat3_identity(); 138 | mat4 mat4_identity(); 139 | 140 | mat3 mat3_mul(mat3 a, mat3 b); 141 | void mat3_set(mat3* mat, mat3 o); 142 | 143 | mat3 mat3_translate(vec2 v); 144 | mat3 mat3_rotate(f32 r); 145 | mat3 mat3_scalev(vec2 s); 146 | mat3 mat3_scalef(f32 s); 147 | 148 | mat4 mat4_mul(mat4 a, mat4 b); 149 | void mat4_set(mat4* mat, mat4 o); 150 | mat4 mat4_transpose(mat4 a); 151 | 152 | mat4 mat4_translate(vec3 v); 153 | mat4 mat4_scale(vec3 v); 154 | mat4 mat4_rotX(f32 deg); 155 | mat4 mat4_rotY(f32 deg); 156 | mat4 mat4_rotZ(f32 deg); 157 | mat4 mat4_ortho(f32 left, f32 right, f32 top, f32 bottom, f32 near, f32 far); 158 | mat4 mat4_perspective(f32 fov, f32 aspect_ratio, f32 near, f32 far); 159 | 160 | //~ Quaternion Functions 161 | 162 | quat quat_identity(); 163 | 164 | quat quat_mul(quat a, quat b); 165 | f32 quat_length(quat q); 166 | quat quat_norm(quat q); 167 | quat quat_rotate_axis(quat q, f32 x, f32 y, f32 z, f32 a); 168 | quat quat_from_euler(f32 yaw, f32 pitch, f32 roll); 169 | mat4 quat_to_rotation_mat(quat q); 170 | 171 | //~ Rect Functions 172 | 173 | b8 rect_contains_point(rect a, vec2 p); 174 | b8 rect_overlaps(rect a, rect b); 175 | b8 rect_contained_by_rect(rect a, rect b); 176 | rect rect_get_overlap(rect a, rect b); 177 | rect rect_uv_cull(rect quad, rect uv, rect cull_quad); 178 | 179 | #endif //VMATH_H 180 | -------------------------------------------------------------------------------- /source/core/backend.c: -------------------------------------------------------------------------------- 1 | #include "backend.h" 2 | 3 | #if defined(BACKEND_GL46) 4 | 5 | # if defined(PLATFORM_WIN) 6 | # include "impl/win32_gl46_backend.c" 7 | # elif defined(PLATFORM_LINUX) 8 | # include "impl/linux_gl46_backend.c" 9 | # endif // WINDOWS 10 | 11 | #elif defined(BACKEND_GL33) 12 | 13 | # if defined(PLATFORM_WIN) 14 | # include "impl/win32_gl33_backend.c" 15 | # elif defined(PLATFORM_LINUX) 16 | # include "impl/linux_gl33_backend.c" 17 | # endif // WINDOWS 18 | 19 | #elif defined(BACKEND_D3D11) 20 | 21 | # if defined(PLATFORM_WIN) 22 | # include "impl/win32_d3d11_backend.c" 23 | # elif defined(PLATFORM_LINUX) 24 | # error The D3D11 Backend is not supported for linux 25 | # endif // WINDOWS 26 | 27 | #endif // Backends 28 | -------------------------------------------------------------------------------- /source/core/backend.h: -------------------------------------------------------------------------------- 1 | /* date = July 5th 2022 6:32 pm */ 2 | 3 | #ifndef BACKEND_H 4 | #define BACKEND_H 5 | 6 | #include "defines.h" 7 | #include "base/base.h" 8 | 9 | #include "os/window.h" 10 | 11 | //~ Initialization 12 | void B_BackendInit(OS_Window* window); 13 | void B_BackendInitShared(OS_Window* window, OS_Window* share); 14 | 15 | void B_BackendSelectRenderWindow(OS_Window* window); 16 | void B_BackendSwapchainNext(OS_Window* window); 17 | void B_BackendFree(OS_Window* window); 18 | 19 | #endif //BACKEND_H 20 | -------------------------------------------------------------------------------- /source/core/impl/d3d11_functions.c: -------------------------------------------------------------------------------- 1 | #include "d3d11_functions.h" 2 | 3 | #if defined(DXGI_FUNCTIONS) 4 | 5 | //# define X(Name, Return, Args) DXGI_##Name##_Func* Name; 6 | //DXGI_FUNCTIONS 7 | //# undef X 8 | // 9 | void __LoadDXGIFunctions(void) { 10 | //#define X(Name, Return, Args) \ 11 | //if (!Name) Name = (DXGI_##Name##_Func*) GetProcAddress(#Name); 12 | // 13 | //DXGI_FUNCTIONS 14 | // 15 | //#undef X 16 | } 17 | 18 | #endif // defined(DXGI_FUNCTIONS) -------------------------------------------------------------------------------- /source/core/impl/d3d11_functions.h: -------------------------------------------------------------------------------- 1 | /* date = March 22nd 2023 0:00 pm */ 2 | 3 | #ifndef D3D11_FUNCTIONS_H 4 | #define D3D11_FUNCTIONS_H 5 | 6 | #include "defines.h" 7 | 8 | #if defined(_DEBUG) 9 | #define CHECK_HR(hrcall) Statement(\ 10 | u64 start = 0;\ 11 | if (!IsDebuggerPresent())\ 12 | start = IDXGIInfoQueue_GetNumStoredMessages(s_wnd->dbg_queue, DXGI_DEBUG_ALL);\ 13 | \ 14 | if (FAILED(hr = hrcall)) {\ 15 | if (IsDebuggerPresent()) {\ 16 | LogError("[D3D11 Backend] Function call failed: %s", #hrcall);\ 17 | LogError("[D3D11 Backend] Check Debugger Debug Output");\ 18 | } else {\ 19 | u64 end =\ 20 | IDXGIInfoQueue_GetNumStoredMessages(s_wnd->dbg_queue,\ 21 | DXGI_DEBUG_ALL);\ 22 | \ 23 | M_Scratch scratch = scratch_get();\ 24 | for (u64 i = start; i < end; i++) {\ 25 | SIZE_T msg_size = 0;\ 26 | IDXGIInfoQueue_GetMessage(s_wnd->dbg_queue,\ 27 | DXGI_DEBUG_ALL, i, nullptr,\ 28 | &msg_size);\ 29 | DXGI_INFO_QUEUE_MESSAGE* msg = arena_alloc(&scratch.arena, msg_size);\ 30 | IDXGIInfoQueue_GetMessage(s_wnd->dbg_queue,\ 31 | DXGI_DEBUG_ALL, i, msg,\ 32 | &msg_size);\ 33 | LogError("[D3D11 Backend] %s", msg->pDescription);\ 34 | scratch_reset(&scratch);\ 35 | }\ 36 | scratch_return(&scratch);\ 37 | }\ 38 | }\ 39 | ) 40 | #else 41 | #define CHECK_HR(hrcall) Statement(\ 42 | if (FAILED(hr = hrcall)) {\ 43 | LogError("[D3D11 Backend] Function call failed: %s", #hrcall);\ 44 | LogError("[D3D11 Backend] Enable Debug mode by defining _DEBUG to know more");\ 45 | }\ 46 | ) 47 | #endif 48 | 49 | #define SAFE_RELEASE(release, obj) if (obj) release##_Release(obj) 50 | 51 | 52 | 53 | #if defined(BACKEND_D3D11) 54 | # define DXGI_FUNCTIONS \ 55 | X(DXGIGetDebugInterface, HRESULT, (REFIID riid, void **ppDebug)) 56 | #else 57 | # define DXGI_FUNCTIONS 58 | #endif 59 | 60 | 61 | //#define X(Name, Return, Args)\ 62 | //typedef Return DXGI_##Name##_Func Args;\ 63 | //extern DXGI_##Name##_Func* Name; 64 | //DXGI_FUNCTIONS 65 | //#undef X 66 | 67 | 68 | #endif //D3D11_FUNCTIONS_H 69 | -------------------------------------------------------------------------------- /source/core/impl/d3d11_resources.h: -------------------------------------------------------------------------------- 1 | /* date = March 27th 2023 3:35 pm */ 2 | 3 | #ifndef D3D11_RESOURCES_H 4 | #define D3D11_RESOURCES_H 5 | 6 | #define D3D11_NO_HELPERS 7 | #define CINTERFACE 8 | #define COBJMACROS 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | HashTable_Prototype(string, i32); 15 | 16 | typedef struct R_Buffer { 17 | R_BufferFlags flags; 18 | ID3D11Buffer* handle; 19 | u32 v_stride; 20 | } R_Buffer; 21 | 22 | typedef struct R_UniformBuffer { 23 | R_ShaderType stage; 24 | string name; 25 | hash_table(string, i32) uniform_offsets; 26 | u8* cpu_side_buffer; 27 | b8 dirty; 28 | u32 size; 29 | ID3D11Buffer* handle; 30 | } R_UniformBuffer; 31 | 32 | typedef struct R_Shader { 33 | R_ShaderType type; 34 | ID3D10Blob* bytecode_blob; 35 | union { 36 | ID3D11VertexShader* vs; 37 | ID3D11PixelShader* ps; 38 | ID3D11GeometryShader* gs; 39 | }; 40 | } R_Shader; 41 | 42 | typedef struct R_ShaderPack { 43 | R_Shader vs; 44 | R_Shader ps; 45 | R_Shader gs; 46 | } R_ShaderPack; 47 | 48 | typedef struct R_BufferAttribCountPack { 49 | R_Buffer* b; 50 | u32 attrib_count; 51 | } R_BufferAttribCountPack; 52 | 53 | DArray_Prototype(R_BufferAttribCountPack); 54 | 55 | typedef R_UniformBuffer* R_UniformBufferHandle; 56 | DArray_Prototype(R_UniformBufferHandle); 57 | 58 | typedef struct R_Pipeline { 59 | R_InputAssembly assembly; 60 | R_Attribute* attributes; 61 | R_ShaderPack* shader; 62 | R_BlendMode blend_mode; 63 | u32 attribute_count; 64 | 65 | // yikes! 66 | darray(R_UniformBufferHandle) vs_uniform_buffers; 67 | darray(R_UniformBufferHandle) ps_uniform_buffers; 68 | darray(R_UniformBufferHandle) gs_uniform_buffers; 69 | 70 | darray(R_BufferAttribCountPack) buffers; 71 | ID3D11InputLayout* layout; 72 | ID3D11BlendState* blend_state; 73 | b8 layout_changed; 74 | } R_Pipeline; 75 | 76 | typedef struct R_Texture2D { 77 | u32 width; 78 | u32 height; 79 | 80 | R_TextureFormat format; 81 | R_TextureResizeParam min; 82 | R_TextureResizeParam mag; 83 | R_TextureWrapParam wrap_s; 84 | R_TextureWrapParam wrap_t; 85 | R_TextureMutability mut; 86 | R_TextureUsage usage; 87 | 88 | ID3D11Texture2D* handle; 89 | ID3D11ShaderResourceView* shader_resource_view; 90 | ID3D11RenderTargetView* render_target_view; 91 | ID3D11SamplerState* sampler; 92 | } R_Texture2D; 93 | 94 | typedef struct R_Framebuffer { 95 | u8 temp; 96 | } R_Framebuffer; 97 | 98 | #endif //D3D11_RESOURCES_H 99 | -------------------------------------------------------------------------------- /source/core/impl/gl33_resources.h: -------------------------------------------------------------------------------- 1 | /* date = March 27th 2023 0:38 pm */ 2 | 3 | #ifndef GL33_RESOURCES_H 4 | #define GL33_RESOURCES_H 5 | 6 | HashTable_Prototype(string, i32); 7 | 8 | typedef struct R_Buffer { 9 | R_BufferFlags flags; 10 | u32 handle; 11 | } R_Buffer; 12 | 13 | typedef struct R_UniformBuffer { 14 | R_ShaderType stage; 15 | string name; 16 | hash_table(string, i32) uniform_offsets; 17 | u8* cpu_side_buffer; 18 | b8 dirty; 19 | u32 size; 20 | u32 bindpoint; 21 | u32 handle; 22 | } R_UniformBuffer; 23 | 24 | typedef struct R_Shader { 25 | R_ShaderType type; 26 | u32 handle; 27 | } R_Shader; 28 | 29 | typedef struct R_ShaderPack { 30 | hash_table(string, i32) uniforms; 31 | u32 handle; 32 | } R_ShaderPack; 33 | 34 | typedef R_UniformBuffer* R_UniformBufferHandle; 35 | DArray_Prototype(R_UniformBufferHandle); 36 | 37 | typedef struct R_Pipeline { 38 | R_InputAssembly assembly; 39 | R_Attribute* attributes; 40 | R_ShaderPack* shader; 41 | R_BlendMode blend_mode; 42 | u32 attribute_count; 43 | 44 | darray(R_UniformBufferHandle) uniform_buffers; 45 | 46 | u32 bindpoint; 47 | u32 attribpoint; 48 | u32 handle; 49 | } R_Pipeline; 50 | 51 | typedef struct R_Texture2D { 52 | u32 width; 53 | u32 height; 54 | 55 | R_TextureFormat format; 56 | R_TextureResizeParam min; 57 | R_TextureResizeParam mag; 58 | R_TextureWrapParam wrap_s; 59 | R_TextureWrapParam wrap_t; 60 | R_TextureMutability mut; 61 | R_TextureUsage usage; 62 | 63 | u32 handle; 64 | } R_Texture2D; 65 | 66 | typedef struct R_Framebuffer { 67 | u32 width; 68 | u32 height; 69 | 70 | R_Texture2D* color_attachments; 71 | u32 color_attachment_count; 72 | R_Texture2D depth_attachment; 73 | 74 | u32 handle; 75 | } R_Framebuffer; 76 | 77 | 78 | #endif //GL33_RESOURCES_H 79 | -------------------------------------------------------------------------------- /source/core/impl/gl46_resources.h: -------------------------------------------------------------------------------- 1 | /* date = March 27th 2023 0:59 pm */ 2 | 3 | #ifndef GL46_RESOURCES_H 4 | #define GL46_RESOURCES_H 5 | 6 | HashTable_Prototype(string, i32); 7 | 8 | typedef struct R_Buffer { 9 | R_BufferFlags flags; 10 | u32 handle; 11 | 12 | union { 13 | string buffer_name; 14 | }; 15 | } R_Buffer; 16 | 17 | typedef struct R_UniformBuffer { 18 | R_ShaderType stage; 19 | string name; 20 | hash_table(string, i32) uniform_offsets; 21 | u8* cpu_side_buffer; 22 | b8 dirty; 23 | u32 size; 24 | u32 bindpoint; 25 | u32 handle; 26 | } R_UniformBuffer; 27 | 28 | typedef struct R_Shader { 29 | R_ShaderType type; 30 | u32 handle; 31 | } R_Shader; 32 | 33 | typedef struct R_ShaderPack { 34 | hash_table(string, i32) uniforms; 35 | u32 handle; 36 | } R_ShaderPack; 37 | 38 | typedef R_UniformBuffer* R_UniformBufferHandle; 39 | DArray_Prototype(R_UniformBufferHandle); 40 | 41 | typedef struct R_Pipeline { 42 | R_InputAssembly assembly; 43 | R_Attribute* attributes; 44 | R_ShaderPack* shader; 45 | R_BlendMode blend_mode; 46 | u32 attribute_count; 47 | 48 | darray(R_UniformBufferHandle) uniform_buffers; 49 | 50 | u32 bindpoint; 51 | u32 attribpoint; 52 | u32 handle; 53 | } R_Pipeline; 54 | 55 | typedef struct R_Texture2D { 56 | u32 width; 57 | u32 height; 58 | 59 | R_TextureFormat format; 60 | R_TextureResizeParam min; 61 | R_TextureResizeParam mag; 62 | R_TextureWrapParam wrap_s; 63 | R_TextureWrapParam wrap_t; 64 | R_TextureMutability mut; 65 | R_TextureUsage usage; 66 | 67 | u32 handle; 68 | } R_Texture2D; 69 | 70 | typedef struct R_Framebuffer { 71 | u32 width; 72 | u32 height; 73 | 74 | R_Texture2D* color_attachments; 75 | u32 color_attachment_count; 76 | R_Texture2D depth_attachment; 77 | 78 | u32 handle; 79 | } R_Framebuffer; 80 | 81 | 82 | #endif //GL46_RESOURCES_H 83 | -------------------------------------------------------------------------------- /source/core/impl/gl_functions.c: -------------------------------------------------------------------------------- 1 | #include "gl_functions.h" 2 | 3 | #if defined(GL_FUNCTIONS) 4 | 5 | typedef i64 long_func(); 6 | typedef long_func* loader_func(const char* name); 7 | 8 | # define X(Name, Return, Args) GL_##Name##_Func* Name; 9 | GL_FUNCTIONS 10 | GL_DEBUG_FUNCTIONS 11 | # undef X 12 | 13 | 14 | void __LoadGLFunctions(loader_func* load_proc, loader_func* fallback) { 15 | #define X(Name, Return, Args) \ 16 | Name = (GL_##Name##_Func *) load_proc(#Name);\ 17 | if (!Name) Name = (GL_##Name##_Func *) fallback(#Name); 18 | 19 | GL_FUNCTIONS; 20 | GL_DEBUG_FUNCTIONS; 21 | 22 | #undef X 23 | } 24 | 25 | #endif // defined(GL_FUNCTIONS) 26 | -------------------------------------------------------------------------------- /source/core/impl/linux_gl33_backend.c: -------------------------------------------------------------------------------- 1 | 2 | #include "gl_functions.h" 3 | #include "os/impl/x11_window.h" 4 | #include "base/log.h" 5 | #include 6 | 7 | // TODO(voxel): 8 | // TODO(voxel): Maybe switch to egl because apparently it's just better :pain: 9 | // TODO(voxel): Thanks Martins 10 | // TODO(voxel): 11 | 12 | typedef i64 long_func(); 13 | typedef long_func* loader_func(const char* name); 14 | void __LoadGLFunctions(loader_func* load_proc, loader_func* fallback); 15 | 16 | #define GLX_VENDOR 1 17 | #define GLX_RGBA_BIT 0x00000001 18 | #define GLX_WINDOW_BIT 0x00000001 19 | #define GLX_DRAWABLE_TYPE 0x8010 20 | #define GLX_RENDER_TYPE 0x8011 21 | #define GLX_RGBA_TYPE 0x8014 22 | #define GLX_DOUBLEBUFFER 5 23 | #define GLX_STEREO 6 24 | #define GLX_AUX_BUFFERS 7 25 | #define GLX_RED_SIZE 8 26 | #define GLX_GREEN_SIZE 9 27 | #define GLX_BLUE_SIZE 10 28 | #define GLX_ALPHA_SIZE 11 29 | #define GLX_DEPTH_SIZE 12 30 | #define GLX_STENCIL_SIZE 13 31 | #define GLX_ACCUM_RED_SIZE 14 32 | #define GLX_ACCUM_GREEN_SIZE 15 33 | #define GLX_ACCUM_BLUE_SIZE 16 34 | #define GLX_ACCUM_ALPHA_SIZE 17 35 | #define GLX_SAMPLES 0x186a1 36 | #define GLX_VISUAL_ID 0x800b 37 | #define GLX_X_RENDERABLE 0x8012 38 | #define GLX_X_VISUAL_TYPE 0x22 39 | #define GLX_TRUE_COLOR 0x8002 40 | 41 | #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2 42 | #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 43 | #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 44 | #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 45 | #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 46 | #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 47 | #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 48 | #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 49 | #define GLX_CONTEXT_FLAGS_ARB 0x2094 50 | #define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 51 | #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 52 | #define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 53 | #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 54 | #define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 55 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 56 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 57 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 58 | #define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3 59 | 60 | //~ Fn types and loaded pointers 61 | 62 | static void* opengl_module = 0; 63 | 64 | //- These functions are loaded using standard linux so loading 65 | typedef GLXextproc* Linux_glXGetProcAddress(u8* procName); 66 | typedef Bool Linux_glXQueryVersion(Display* display, int* major, int* minor); 67 | typedef GLXFBConfig* Linux_glXChooseFBConfig(Display* display, int screen, const int* attrib_list, int* nelements); 68 | 69 | static Linux_glXGetProcAddress* v_glXGetProcAddress = 0; 70 | static Linux_glXQueryVersion* v_glXQueryVersion = 0; 71 | static Linux_glXChooseFBConfig* v_glXChooseFBConfig = 0; 72 | 73 | //- These functions are loaded using glXGetProcAddress 74 | typedef GLXContext 75 | Linux_glXCreateContextAttribsARBProc(Display*, GLXFBConfig, GLXContext, Bool, const int*); 76 | typedef Bool Linux_glXMakeCurrent(Display*, GLXDrawable, GLXContext); 77 | typedef void Linux_glXSwapBuffers(Display*, GLXDrawable); 78 | typedef void Linux_glXDestroyContext(Display*, GLXContext); 79 | 80 | static Linux_glXCreateContextAttribsARBProc* v_glXCreateContextAttribsARB = 0; 81 | static Linux_glXMakeCurrent* v_glXMakeCurrent = 0; 82 | static Linux_glXSwapBuffers* v_glXSwapBuffers = 0; 83 | static Linux_glXDestroyContext* v_glXDestroyContext = 0; 84 | 85 | 86 | 87 | //~ 88 | 89 | long_func* error_loader(const char* name) { 90 | LogError("[X11 GL33 Backend] Failed to load %s", name); 91 | return (long_func*) nullptr; 92 | } 93 | 94 | long_func* glXGetProcAddress(const char* name) { 95 | return (long_func*) v_glXGetProcAddress((u8*)name); 96 | } 97 | 98 | void B_BackendInitShared(OS_Window* _window, OS_Window* _share) { 99 | 100 | if (!opengl_module || !v_glXGetProcAddress || !v_glXQueryVersion || !v_glXChooseFBConfig) { 101 | const char* sonames[] = { 102 | "libGL.so.1", 103 | "libGL.so", 104 | NULL 105 | }; 106 | 107 | for (u32 i = 0; sonames[i]; i++) { 108 | opengl_module = dlopen(sonames[i], RTLD_LAZY); 109 | if (opengl_module) 110 | break; 111 | } 112 | 113 | v_glXGetProcAddress = (Linux_glXGetProcAddress*) dlsym(opengl_module, "glXGetProcAddress"); 114 | if (!v_glXGetProcAddress) { 115 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXGetProcAddress failed"); 116 | } 117 | v_glXQueryVersion = (Linux_glXQueryVersion*) dlsym(opengl_module, "glXQueryVersion"); 118 | if (!v_glXQueryVersion) { 119 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXQueryVersion failed"); 120 | } 121 | v_glXChooseFBConfig = (Linux_glXChooseFBConfig*) dlsym(opengl_module, "glXChooseFBConfig"); 122 | if (!v_glXChooseFBConfig) { 123 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXChooseFBConfig failed"); 124 | } 125 | } 126 | 127 | if (!v_glXCreateContextAttribsARB || !v_glXMakeCurrent || !v_glXSwapBuffers) { 128 | v_glXCreateContextAttribsARB = (Linux_glXCreateContextAttribsARBProc*) 129 | v_glXGetProcAddress((u8*)"glXCreateContextAttribsARB"); 130 | if (!v_glXCreateContextAttribsARB) { 131 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXCreateContextAttribsARB failed"); 132 | } 133 | v_glXMakeCurrent = (Linux_glXMakeCurrent*) v_glXGetProcAddress((u8*)"glXMakeCurrent"); 134 | if (!v_glXMakeCurrent) { 135 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXMakeCurrent failed"); 136 | } 137 | v_glXSwapBuffers = (Linux_glXSwapBuffers*) v_glXGetProcAddress((u8*)"glXSwapBuffers"); 138 | if (!v_glXSwapBuffers) { 139 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXSwapBuffers failed"); 140 | } 141 | v_glXDestroyContext = (Linux_glXDestroyContext*) 142 | v_glXGetProcAddress((u8*)"glXDestroyContext"); 143 | if (!v_glXSwapBuffers) { 144 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXDestroyContext failed"); 145 | } 146 | } 147 | 148 | X11_Window* window = (X11_Window*) _window; 149 | X11_Window* share = (X11_Window*) _share; 150 | 151 | if (share) { 152 | window->gl_context = share->gl_context; 153 | } else { 154 | static int visual_attribs[] = { 155 | GLX_X_RENDERABLE , true, 156 | GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, 157 | GLX_RENDER_TYPE , GLX_RGBA_BIT, 158 | GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, 159 | GLX_RED_SIZE , 8, 160 | GLX_GREEN_SIZE , 8, 161 | GLX_BLUE_SIZE , 8, 162 | GLX_ALPHA_SIZE , 8, 163 | GLX_DEPTH_SIZE , 24, 164 | GLX_STENCIL_SIZE , 8, 165 | GLX_DOUBLEBUFFER , true, 166 | None 167 | }; 168 | int glx_major, glx_minor; 169 | if (!v_glXQueryVersion(window->display, &glx_major, &glx_minor) || 170 | ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { 171 | LogReturn(, "Invalid GLX version"); 172 | } 173 | 174 | int fbcount; 175 | GLXFBConfig* fbc = v_glXChooseFBConfig(window->display, DefaultScreen(window->display), visual_attribs, &fbcount); 176 | if (!fbc) { 177 | LogReturn(, "Failed to retrieve a framebuffer config\n"); 178 | } 179 | 180 | static int context_attribs[] = { 181 | GLX_CONTEXT_MAJOR_VERSION_ARB, 3, 182 | GLX_CONTEXT_MINOR_VERSION_ARB, 3, 183 | GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 184 | None 185 | }; 186 | 187 | window->gl_context = v_glXCreateContextAttribsARB(window->display, fbc[0], NULL, true, context_attribs); 188 | 189 | __LoadGLFunctions(glXGetProcAddress, error_loader); 190 | } 191 | 192 | v_glXMakeCurrent(window->display, window->handle, window->gl_context); 193 | } 194 | 195 | 196 | 197 | void B_BackendInit(OS_Window* _window) { 198 | B_BackendInitShared(_window, 0); 199 | } 200 | 201 | void B_BackendSelectRenderWindow(OS_Window* _window) { 202 | X11_Window* window = (X11_Window*) _window; 203 | v_glXMakeCurrent(window->display, window->handle, window->gl_context); 204 | } 205 | 206 | void B_BackendSwapchainNext(OS_Window* _window) { 207 | X11_Window* window = (X11_Window*) _window; 208 | v_glXSwapBuffers(window->display, window->handle); 209 | } 210 | 211 | void B_BackendFree(OS_Window* _window) { 212 | X11_Window* window = (X11_Window*) _window; 213 | v_glXMakeCurrent(window->display, window->handle, 0); 214 | v_glXDestroyContext(window->display, window->gl_context); 215 | } 216 | -------------------------------------------------------------------------------- /source/core/impl/linux_gl46_backend.c: -------------------------------------------------------------------------------- 1 | 2 | #include "gl_functions.h" 3 | #include "os/impl/x11_window.h" 4 | #include "base/log.h" 5 | #include 6 | 7 | // TODO(voxel): 8 | // TODO(voxel): Maybe switch to egl because apparently it's just better :pain: 9 | // TODO(voxel): Thanks Martins 10 | // TODO(voxel): 11 | 12 | typedef i64 long_func(); 13 | typedef long_func* loader_func(const char* name); 14 | void __LoadGLFunctions(loader_func* load_proc, loader_func* fallback); 15 | 16 | #define GLX_VENDOR 1 17 | #define GLX_RGBA_BIT 0x00000001 18 | #define GLX_WINDOW_BIT 0x00000001 19 | #define GLX_DRAWABLE_TYPE 0x8010 20 | #define GLX_RENDER_TYPE 0x8011 21 | #define GLX_RGBA_TYPE 0x8014 22 | #define GLX_DOUBLEBUFFER 5 23 | #define GLX_STEREO 6 24 | #define GLX_AUX_BUFFERS 7 25 | #define GLX_RED_SIZE 8 26 | #define GLX_GREEN_SIZE 9 27 | #define GLX_BLUE_SIZE 10 28 | #define GLX_ALPHA_SIZE 11 29 | #define GLX_DEPTH_SIZE 12 30 | #define GLX_STENCIL_SIZE 13 31 | #define GLX_ACCUM_RED_SIZE 14 32 | #define GLX_ACCUM_GREEN_SIZE 15 33 | #define GLX_ACCUM_BLUE_SIZE 16 34 | #define GLX_ACCUM_ALPHA_SIZE 17 35 | #define GLX_SAMPLES 0x186a1 36 | #define GLX_VISUAL_ID 0x800b 37 | #define GLX_X_RENDERABLE 0x8012 38 | #define GLX_X_VISUAL_TYPE 0x22 39 | #define GLX_TRUE_COLOR 0x8002 40 | 41 | #define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2 42 | #define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 43 | #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 44 | #define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 45 | #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 46 | #define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 47 | #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 48 | #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 49 | #define GLX_CONTEXT_FLAGS_ARB 0x2094 50 | #define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 51 | #define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 52 | #define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 53 | #define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 54 | #define GLX_NO_RESET_NOTIFICATION_ARB 0x8261 55 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 56 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0 57 | #define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 58 | #define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3 59 | 60 | void 61 | MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void *userParam) { 62 | LogError("[GL46 Backend] OpenGL Error: %s", message); 63 | } 64 | 65 | 66 | //~ Fn types and loaded pointers 67 | 68 | static void* opengl_module = 0; 69 | 70 | //- These functions are loaded using standard linux so loading 71 | typedef GLXextproc* Linux_glXGetProcAddress(u8* procName); 72 | typedef Bool Linux_glXQueryVersion(Display* display, int* major, int* minor); 73 | typedef GLXFBConfig* Linux_glXChooseFBConfig(Display* display, int screen, const int* attrib_list, int* nelements); 74 | 75 | static Linux_glXGetProcAddress* v_glXGetProcAddress = 0; 76 | static Linux_glXQueryVersion* v_glXQueryVersion = 0; 77 | static Linux_glXChooseFBConfig* v_glXChooseFBConfig = 0; 78 | 79 | //- These functions are loaded using glXGetProcAddress 80 | typedef GLXContext 81 | Linux_glXCreateContextAttribsARBProc(Display*, GLXFBConfig, GLXContext, Bool, const int*); 82 | typedef Bool Linux_glXMakeCurrent(Display*, GLXDrawable, GLXContext); 83 | typedef void Linux_glXSwapBuffers(Display*, GLXDrawable); 84 | typedef void Linux_glXDestroyContext(Display*, GLXContext); 85 | 86 | static Linux_glXCreateContextAttribsARBProc* v_glXCreateContextAttribsARB = 0; 87 | static Linux_glXMakeCurrent* v_glXMakeCurrent = 0; 88 | static Linux_glXSwapBuffers* v_glXSwapBuffers = 0; 89 | static Linux_glXDestroyContext* v_glXDestroyContext = 0; 90 | 91 | 92 | 93 | //~ 94 | 95 | long_func* error_loader(const char* name) { 96 | LogError("[X11 GL33 Backend] Failed to load %s", name); 97 | return (long_func*) nullptr; 98 | } 99 | 100 | long_func* glXGetProcAddress(const char* name) { 101 | return (long_func*) v_glXGetProcAddress((u8*)name); 102 | } 103 | 104 | void B_BackendInitShared(OS_Window* _window, OS_Window* _share) { 105 | 106 | if (!opengl_module || !v_glXGetProcAddress || !v_glXQueryVersion || !v_glXChooseFBConfig) { 107 | const char* sonames[] = { 108 | "libGL.so.1", 109 | "libGL.so", 110 | NULL 111 | }; 112 | 113 | for (u32 i = 0; sonames[i]; i++) { 114 | opengl_module = dlopen(sonames[i], RTLD_LAZY); 115 | if (opengl_module) 116 | break; 117 | } 118 | 119 | v_glXGetProcAddress = (Linux_glXGetProcAddress*) dlsym(opengl_module, "glXGetProcAddress"); 120 | if (!v_glXGetProcAddress) { 121 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXGetProcAddress failed"); 122 | } 123 | v_glXQueryVersion = (Linux_glXQueryVersion*) dlsym(opengl_module, "glXQueryVersion"); 124 | if (!v_glXQueryVersion) { 125 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXQueryVersion failed"); 126 | } 127 | v_glXChooseFBConfig = (Linux_glXChooseFBConfig*) dlsym(opengl_module, "glXChooseFBConfig"); 128 | if (!v_glXChooseFBConfig) { 129 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXChooseFBConfig failed"); 130 | } 131 | } 132 | 133 | if (!v_glXCreateContextAttribsARB || !v_glXMakeCurrent || !v_glXSwapBuffers) { 134 | v_glXCreateContextAttribsARB = (Linux_glXCreateContextAttribsARBProc*) 135 | v_glXGetProcAddress((u8*)"glXCreateContextAttribsARB"); 136 | if (!v_glXCreateContextAttribsARB) { 137 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXCreateContextAttribsARB failed"); 138 | } 139 | v_glXMakeCurrent = (Linux_glXMakeCurrent*) v_glXGetProcAddress((u8*)"glXMakeCurrent"); 140 | if (!v_glXMakeCurrent) { 141 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXMakeCurrent failed"); 142 | } 143 | v_glXSwapBuffers = (Linux_glXSwapBuffers*) v_glXGetProcAddress((u8*)"glXSwapBuffers"); 144 | if (!v_glXSwapBuffers) { 145 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXSwapBuffers failed"); 146 | } 147 | v_glXDestroyContext = (Linux_glXDestroyContext*) 148 | v_glXGetProcAddress((u8*)"glXDestroyContext"); 149 | if (!v_glXSwapBuffers) { 150 | LogReturn(, "Linux OpenGL GLX Function Loading: Loading glXDestroyContext failed"); 151 | } 152 | } 153 | 154 | X11_Window* window = (X11_Window*) _window; 155 | X11_Window* share = (X11_Window*) _share; 156 | 157 | if (share) { 158 | window->gl_context = share->gl_context; 159 | } else { 160 | static int visual_attribs[] = { 161 | GLX_X_RENDERABLE , true, 162 | GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, 163 | GLX_RENDER_TYPE , GLX_RGBA_BIT, 164 | GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, 165 | GLX_RED_SIZE , 8, 166 | GLX_GREEN_SIZE , 8, 167 | GLX_BLUE_SIZE , 8, 168 | GLX_ALPHA_SIZE , 8, 169 | GLX_DEPTH_SIZE , 24, 170 | GLX_STENCIL_SIZE , 8, 171 | GLX_DOUBLEBUFFER , true, 172 | None 173 | }; 174 | int glx_major, glx_minor; 175 | if (!v_glXQueryVersion(window->display, &glx_major, &glx_minor) || 176 | ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) { 177 | LogReturn(, "Invalid GLX version"); 178 | } 179 | 180 | int fbcount; 181 | GLXFBConfig* fbc = v_glXChooseFBConfig(window->display, DefaultScreen(window->display), visual_attribs, &fbcount); 182 | if (!fbc) { 183 | LogReturn(, "Failed to retrieve a framebuffer config\n"); 184 | } 185 | 186 | static int context_attribs[] = { 187 | GLX_CONTEXT_MAJOR_VERSION_ARB, 4, 188 | GLX_CONTEXT_MINOR_VERSION_ARB, 6, 189 | GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, 190 | #if defined (_DEBUG) 191 | GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, 192 | #endif 193 | None 194 | }; 195 | 196 | window->gl_context = v_glXCreateContextAttribsARB(window->display, fbc[0], NULL, true, context_attribs); 197 | 198 | __LoadGLFunctions(glXGetProcAddress, error_loader); 199 | } 200 | 201 | v_glXMakeCurrent(window->display, window->handle, window->gl_context); 202 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 203 | glDebugMessageCallback(MessageCallback, 0); 204 | } 205 | 206 | void B_BackendInit(OS_Window* _window) { 207 | B_BackendInitShared(_window, 0); 208 | } 209 | 210 | void B_BackendSelectRenderWindow(OS_Window* _window) { 211 | X11_Window* window = (X11_Window*) _window; 212 | v_glXMakeCurrent(window->display, window->handle, window->gl_context); 213 | 214 | } 215 | 216 | void B_BackendSwapchainNext(OS_Window* _window) { 217 | X11_Window* window = (X11_Window*) _window; 218 | v_glXSwapBuffers(window->display, window->handle); 219 | } 220 | 221 | void B_BackendFree(OS_Window* _window) { 222 | X11_Window* window = (X11_Window*) _window; 223 | v_glXMakeCurrent(window->display, window->handle, 0); 224 | v_glXDestroyContext(window->display, window->gl_context); 225 | } 226 | -------------------------------------------------------------------------------- /source/core/impl/win32_d3d11_backend.c: -------------------------------------------------------------------------------- 1 | #define D3D11_NO_HELPERS 2 | #define CINTERFACE 3 | #define COBJMACROS 4 | #include 5 | #include 6 | 7 | #include "defines.h" 8 | 9 | #define WIN32_LEAN_AND_MEAN 10 | #include 11 | #include "os/impl/win32_window.h" 12 | 13 | #include "d3d11_functions.h" 14 | 15 | // Talking with resources layer 16 | void __SetCurrentWindow(W32_Window* window); 17 | void __LoadDXGIFunctions(void); 18 | void R_Viewport(i32 x, i32 y, i32 w, i32 h); 19 | 20 | typedef HRESULT W32_D3D11CreateDeviceAndSwapChain(IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, 21 | HMODULE Software, UINT Flags, 22 | const D3D_FEATURE_LEVEL* pFeatureLevels, 23 | UINT FeatureLevels, UINT SDKVersion, 24 | const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, 25 | IDXGISwapChain** ppSwapChain, 26 | ID3D11Device** ppDevice, 27 | D3D_FEATURE_LEVEL* pFeatureLevel, 28 | ID3D11DeviceContext** ppImmediateContext); 29 | 30 | typedef HRESULT W32_DXGIGetDebugInterface(REFIID riid, void **ppDebug); 31 | 32 | 33 | static HMODULE d3d11_module; 34 | static HMODULE dxgidebug_module; 35 | static W32_D3D11CreateDeviceAndSwapChain* v_d3d11CreateDeviceAndSwapchain; 36 | static W32_DXGIGetDebugInterface* v_dxgiGetDebugInterface; 37 | 38 | void B_BackendInit(OS_Window* _window) { 39 | W32_Window* window = (W32_Window*)_window; 40 | 41 | if (!d3d11_module) { 42 | d3d11_module = LoadLibraryA("D3D11.dll"); 43 | 44 | v_d3d11CreateDeviceAndSwapchain = (W32_D3D11CreateDeviceAndSwapChain*) 45 | GetProcAddress(d3d11_module, "D3D11CreateDeviceAndSwapChain"); 46 | } 47 | if (!dxgidebug_module) { 48 | dxgidebug_module = LoadLibraryA("dxgidebug.dll"); 49 | 50 | v_dxgiGetDebugInterface = (W32_DXGIGetDebugInterface*) 51 | GetProcAddress(dxgidebug_module, "DXGIGetDebugInterface"); 52 | } 53 | 54 | DXGI_SWAP_CHAIN_DESC swapchain_desc = {0}; 55 | swapchain_desc.BufferDesc.Width = 0; 56 | swapchain_desc.BufferDesc.Height = 0; 57 | swapchain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 58 | swapchain_desc.BufferDesc.RefreshRate.Numerator = 0; 59 | swapchain_desc.BufferDesc.RefreshRate.Denominator = 0; 60 | swapchain_desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; 61 | swapchain_desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; 62 | swapchain_desc.SampleDesc.Count = 1; 63 | swapchain_desc.SampleDesc.Quality = 0; 64 | swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 65 | swapchain_desc.BufferCount = 1; 66 | swapchain_desc.OutputWindow = window->handle; 67 | swapchain_desc.Windowed = true; 68 | swapchain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 69 | swapchain_desc.Flags = 0; 70 | 71 | HRESULT hr; 72 | 73 | u32 flags = 0; 74 | #if defined(_DEBUG) 75 | flags |= D3D11_CREATE_DEVICE_DEBUG; 76 | #endif 77 | 78 | if (FAILED(hr = v_d3d11CreateDeviceAndSwapchain(nullptr, 79 | D3D_DRIVER_TYPE_HARDWARE, 80 | nullptr, 81 | flags, 82 | nullptr, 83 | 0, 84 | D3D11_SDK_VERSION, 85 | &swapchain_desc, 86 | &window->swapchain, 87 | &window->device, 88 | nullptr, 89 | &window->context))) { 90 | LogError("[D3D11 Backend] Create Device and Swapchain Failed"); 91 | } 92 | 93 | #if defined(_DEBUG) 94 | if (IsDebuggerPresent()) { 95 | ID3D11InfoQueue* info; 96 | ID3D11Device_QueryInterface(window->device, &IID_ID3D11InfoQueue, (void**)&info); 97 | ID3D11InfoQueue_SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_CORRUPTION, TRUE); 98 | ID3D11InfoQueue_SetBreakOnSeverity(info, D3D11_MESSAGE_SEVERITY_ERROR, TRUE); 99 | ID3D11InfoQueue_Release(info); 100 | } else { 101 | if (FAILED(v_dxgiGetDebugInterface(&IID_IDXGIInfoQueue, (void**)&window->dbg_queue))) { 102 | LogError("[D3D11 Backend] Couldn't get the Debug Interfrace from DXGI"); 103 | } 104 | } 105 | #endif 106 | 107 | ID3D11Resource* back_buffer_resource = nullptr; 108 | IDXGISwapChain_GetBuffer(window->swapchain, 0, &IID_ID3D11Resource, (void**) &back_buffer_resource); 109 | ID3D11Device_CreateRenderTargetView(window->device, back_buffer_resource, nullptr, &window->rtv); 110 | ID3D11Resource_Release(back_buffer_resource); 111 | 112 | __LoadDXGIFunctions(); 113 | 114 | __SetCurrentWindow(window); 115 | R_Viewport(0, 0, window->width, window->height); 116 | 117 | ID3D11RasterizerState* rstate; 118 | D3D11_RASTERIZER_DESC rdesc = {0}; 119 | rdesc.FillMode = D3D11_FILL_SOLID; 120 | rdesc.CullMode = D3D11_CULL_NONE; 121 | 122 | ID3D11Device_CreateRasterizerState(window->device, &rdesc, &rstate); 123 | ID3D11DeviceContext_RSSetState(window->context, rstate); 124 | ID3D11RasterizerState_Release(rstate); 125 | } 126 | 127 | void B_BackendInitShared(OS_Window* window, OS_Window* share) { 128 | // TODO(voxel): 129 | } 130 | 131 | void B_BackendSelectRenderWindow(OS_Window* _window) { 132 | W32_Window* window = (W32_Window*)_window; 133 | // TODO(voxel): OMSetRenderTarget here 134 | __SetCurrentWindow(window); 135 | } 136 | 137 | void B_BackendSwapchainNext(OS_Window* _window) { 138 | W32_Window* window = (W32_Window*)_window; 139 | 140 | // NOTE(voxel): sync interval (2nd param) is set to 0 for uncapped fps 141 | IDXGISwapChain_Present(window->swapchain, 0, 0); 142 | } 143 | 144 | void B_BackendFree(OS_Window* _window) { 145 | W32_Window* window = (W32_Window*)_window; 146 | 147 | SAFE_RELEASE(IDXGIInfoQueue, window->dbg_queue); 148 | SAFE_RELEASE(ID3D11RenderTargetView, window->rtv); 149 | SAFE_RELEASE(ID3D11DeviceContext, window->context); 150 | SAFE_RELEASE(IDXGISwapChain, window->swapchain); 151 | SAFE_RELEASE(ID3D11Device, window->device); 152 | } 153 | -------------------------------------------------------------------------------- /source/core/impl/win32_gl33_backend.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "gl_functions.h" 4 | #include "os/impl/win32_window.h" 5 | 6 | typedef i64 long_func(); 7 | typedef long_func* loader_func(const char* name); 8 | void __LoadGLFunctions(loader_func* load_proc, loader_func* fallback); 9 | 10 | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 11 | #define WGL_DRAW_TO_WINDOW_ARB 0x2001 12 | #define WGL_DRAW_TO_BITMAP_ARB 0x2002 13 | #define WGL_ACCELERATION_ARB 0x2003 14 | #define WGL_NEED_PALETTE_ARB 0x2004 15 | #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 16 | #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 17 | #define WGL_SWAP_METHOD_ARB 0x2007 18 | #define WGL_NUMBER_OVERLAYS_ARB 0x2008 19 | #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 20 | #define WGL_TRANSPARENT_ARB 0x200A 21 | #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 22 | #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 23 | #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 24 | #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A 25 | #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B 26 | #define WGL_SHARE_DEPTH_ARB 0x200C 27 | #define WGL_SHARE_STENCIL_ARB 0x200D 28 | #define WGL_SHARE_ACCUM_ARB 0x200E 29 | #define WGL_SUPPORT_GDI_ARB 0x200F 30 | #define WGL_SUPPORT_OPENGL_ARB 0x2010 31 | #define WGL_DOUBLE_BUFFER_ARB 0x2011 32 | #define WGL_STEREO_ARB 0x2012 33 | #define WGL_PIXEL_TYPE_ARB 0x2013 34 | #define WGL_COLOR_BITS_ARB 0x2014 35 | #define WGL_RED_BITS_ARB 0x2015 36 | #define WGL_RED_SHIFT_ARB 0x2016 37 | #define WGL_GREEN_BITS_ARB 0x2017 38 | #define WGL_GREEN_SHIFT_ARB 0x2018 39 | #define WGL_BLUE_BITS_ARB 0x2019 40 | #define WGL_BLUE_SHIFT_ARB 0x201A 41 | #define WGL_ALPHA_BITS_ARB 0x201B 42 | #define WGL_ALPHA_SHIFT_ARB 0x201C 43 | #define WGL_ACCUM_BITS_ARB 0x201D 44 | #define WGL_ACCUM_RED_BITS_ARB 0x201E 45 | #define WGL_ACCUM_GREEN_BITS_ARB 0x201F 46 | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 47 | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 48 | #define WGL_DEPTH_BITS_ARB 0x2022 49 | #define WGL_STENCIL_BITS_ARB 0x2023 50 | #define WGL_AUX_BUFFERS_ARB 0x2024 51 | #define WGL_NO_ACCELERATION_ARB 0x2025 52 | #define WGL_GENERIC_ACCELERATION_ARB 0x2026 53 | #define WGL_FULL_ACCELERATION_ARB 0x2027 54 | #define WGL_SWAP_EXCHANGE_ARB 0x2028 55 | #define WGL_SWAP_COPY_ARB 0x2029 56 | #define WGL_SWAP_UNDEFINED_ARB 0x202A 57 | #define WGL_TYPE_RGBA_ARB 0x202B 58 | #define WGL_TYPE_COLORINDEX_ARB 0x202C 59 | 60 | #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 61 | #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 62 | #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 63 | #define WGL_CONTEXT_FLAGS_ARB 0x2094 64 | #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 65 | #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 66 | #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 67 | #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 68 | #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 69 | #define ERROR_INVALID_VERSION_ARB 0x2095 70 | #define ERROR_INVALID_PROFILE_ARB 0x2096 71 | 72 | typedef HGLRC WINAPI W32_wglCreateContext(HDC); 73 | typedef BOOL WINAPI W32_wglDeleteContext(HGLRC); 74 | typedef BOOL WINAPI W32_wglMakeCurrent(HDC, HGLRC); 75 | typedef PROC WINAPI W32_wglGetProcAddress(LPCSTR); 76 | 77 | typedef BOOL WINAPI W32_wglChoosePixelFormatARB(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); 78 | typedef HGLRC WINAPI W32_wglCreateContextAttribsARB(HDC hdc, HGLRC hShareContext, const int* attribList); 79 | typedef BOOL WINAPI W32_wglSwapLayerBuffers(HDC hdc, UINT plane); 80 | 81 | static HMODULE opengl_module = 0; 82 | 83 | static W32_wglCreateContext* v_wglCreateContext = 0; 84 | 85 | static W32_wglDeleteContext* v_wglDeleteContext = 0; 86 | static W32_wglMakeCurrent* v_wglMakeCurrent = 0; 87 | static W32_wglGetProcAddress* v_wglGetProcAddress = 0; 88 | static W32_wglChoosePixelFormatARB* v_wglChoosePixelFormatARB = 0; 89 | static W32_wglCreateContextAttribsARB* v_wglCreateContextAttribsARB = 0; 90 | 91 | long_func* _GetAddress(const char* name) { 92 | return (long_func*) GetProcAddress(opengl_module, name); 93 | } 94 | 95 | void B_BackendInitShared(OS_Window* _window, OS_Window* _share) { 96 | W32_Window* window = (W32_Window*) _window; 97 | W32_Window* share = (W32_Window*) _share; 98 | 99 | //- Load Preliminary WGL functions 100 | HINSTANCE hinstance = GetModuleHandle(0); 101 | 102 | if (!opengl_module || !v_wglCreateContext || !v_wglDeleteContext || !v_wglMakeCurrent || !v_wglGetProcAddress) { 103 | opengl_module = LoadLibraryA("opengl32.dll"); 104 | v_wglCreateContext = (W32_wglCreateContext*) GetProcAddress(opengl_module, "wglCreateContext"); 105 | if (!v_wglCreateContext) { 106 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglCreateContext failed"); 107 | } 108 | v_wglDeleteContext = (W32_wglDeleteContext*) GetProcAddress(opengl_module, "wglDeleteContext"); 109 | if (!v_wglDeleteContext) { 110 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglDeleteContext failed"); 111 | } 112 | v_wglMakeCurrent = (W32_wglMakeCurrent*) GetProcAddress(opengl_module, "wglMakeCurrent"); 113 | if (!v_wglMakeCurrent) { 114 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglMakeCurrent failed"); 115 | } 116 | v_wglGetProcAddress = (W32_wglGetProcAddress*) GetProcAddress(opengl_module, "wglGetProcAddress"); 117 | if (!v_wglGetProcAddress) { 118 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglGetProcAddress failed"); 119 | } 120 | } 121 | 122 | //- Create Dummy OpenGL Context 123 | if (!v_wglChoosePixelFormatARB || !v_wglCreateContextAttribsARB) { 124 | WNDCLASSA wc = { 125 | .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, 126 | .lpfnWndProc = DefWindowProcA, 127 | .hInstance = GetModuleHandle(0), 128 | .lpszClassName = "Dummy_WGL_weee", 129 | }; 130 | if (!RegisterClassA(&wc)) { 131 | LogReturn(, "Win32 OpenGL Window: New Class Registration failed"); 132 | } 133 | 134 | HWND bootstrap_window = CreateWindowExA( 135 | 0, 136 | wc.lpszClassName, 137 | "Dummy OpenGL Window", 138 | 0, 139 | CW_USEDEFAULT, 140 | CW_USEDEFAULT, 141 | CW_USEDEFAULT, 142 | CW_USEDEFAULT, 143 | 0, 144 | 0, 145 | wc.hInstance, 146 | 0); 147 | if (!bootstrap_window) { 148 | LogReturn(, "Win32 OpenGL Bootstrap: Window Creation Failed"); 149 | } 150 | 151 | HDC dc = GetDC(bootstrap_window); 152 | 153 | PIXELFORMATDESCRIPTOR format_desc = { 154 | .nSize = sizeof(PIXELFORMATDESCRIPTOR), 155 | .nVersion = 1, 156 | .iPixelType = PFD_TYPE_RGBA, 157 | .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 158 | .cColorBits = 32, 159 | .cAlphaBits = 8, 160 | .iLayerType = PFD_MAIN_PLANE, 161 | .cDepthBits = 24, 162 | .cStencilBits = 8, 163 | }; 164 | 165 | i32 format_idx = ChoosePixelFormat(dc, &format_desc); 166 | if (!format_idx) { 167 | ReleaseDC(bootstrap_window, dc); 168 | LogReturn(, "Win32 OpenGL Bootstrap: Choosing appropriate PixelFormat Failed"); 169 | } 170 | if (!SetPixelFormat(dc, format_idx, &format_desc)) { 171 | ReleaseDC(bootstrap_window, dc); 172 | LogReturn(, "Win32 OpenGL Bootstrap: Setting the PixelFormat Failed"); 173 | } 174 | 175 | HGLRC bootstrap_context = v_wglCreateContext(dc); 176 | if (!bootstrap_context) { 177 | ReleaseDC(bootstrap_window, dc); 178 | LogReturn(, "Win32 OpenGL Bootstrap: Context Creation Failed"); 179 | } 180 | if (!v_wglMakeCurrent(dc, bootstrap_context)) { 181 | ReleaseDC(window->handle, dc); 182 | LogReturn(, "Win32 OpenGL Bootstrap: Context Activation Failed"); 183 | } 184 | 185 | //- Load New ARB WGL functions using Dummy Context 186 | v_wglChoosePixelFormatARB = (W32_wglChoosePixelFormatARB*) v_wglGetProcAddress("wglChoosePixelFormatARB"); 187 | if (!v_wglChoosePixelFormatARB) { 188 | ReleaseDC(bootstrap_window, dc); 189 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglChoosePixelFormatARB failed"); 190 | } 191 | v_wglCreateContextAttribsARB = (W32_wglCreateContextAttribsARB*) v_wglGetProcAddress("wglCreateContextAttribsARB"); 192 | if (!v_wglCreateContextAttribsARB) { 193 | ReleaseDC(bootstrap_window, dc); 194 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglCreateContextAttribsARB failed"); 195 | } 196 | 197 | //- Delete Bootstrapping Stuff 198 | v_wglMakeCurrent(dc, 0); 199 | BOOL delete_context = v_wglDeleteContext(bootstrap_context); 200 | if (!delete_context) { 201 | LogReturn(, "Win32 OpenGL Bootstrap Window Destruction: Context Deletion Failed"); 202 | } 203 | ReleaseDC(bootstrap_window, dc); 204 | if (!DestroyWindow(bootstrap_window)) { 205 | LogReturn(, "Win32 OpenGL Bootstrap Window Destruction: Window Deletion Failed"); 206 | } 207 | UnregisterClassA("Dummy_WGL_weee", hinstance); 208 | } 209 | 210 | //- Create Actual Context 211 | HDC dc = GetDC(window->handle); 212 | int format_attribs_i[] = { 213 | WGL_DRAW_TO_WINDOW_ARB, true, 214 | WGL_SUPPORT_OPENGL_ARB, true, 215 | WGL_DOUBLE_BUFFER_ARB, true, 216 | WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, 217 | WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, 218 | WGL_COLOR_BITS_ARB, 32, 219 | WGL_DEPTH_BITS_ARB, 24, 220 | WGL_STENCIL_BITS_ARB, 8, 221 | 0 222 | }; 223 | 224 | int format_idx; 225 | UINT num_formats; 226 | v_wglChoosePixelFormatARB(dc, format_attribs_i, 0, 1, &format_idx, &num_formats); 227 | if (!num_formats) { 228 | ReleaseDC(window->handle, dc); 229 | LogReturn(, "Win32 OpenGL Window: Context Choosing Pixel Format failed"); 230 | } 231 | 232 | PIXELFORMATDESCRIPTOR format_desc = {0}; 233 | DescribePixelFormat(dc, format_idx, sizeof(PIXELFORMATDESCRIPTOR), &format_desc); 234 | if (!SetPixelFormat(dc, format_idx, &format_desc)) { 235 | ReleaseDC(window->handle, dc); 236 | LogReturn(, "Win32 OpenGL Window: Context SetPixelFormat failed"); 237 | } 238 | 239 | if (share) { 240 | window->glrc = share->glrc; 241 | } else { 242 | int context_attribs[] = { 243 | WGL_CONTEXT_MAJOR_VERSION_ARB, 3, 244 | WGL_CONTEXT_MINOR_VERSION_ARB, 3, 245 | WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 246 | #if defined(_DEBUG) 247 | WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, 248 | #endif 249 | 0, 250 | }; 251 | 252 | window->glrc = v_wglCreateContextAttribsARB(dc, 0, context_attribs); 253 | if (!window->glrc) { 254 | ReleaseDC(window->handle, dc); 255 | LogReturn(, "Win32 OpenGL Window: Context Creation Failed"); 256 | } 257 | if (!v_wglMakeCurrent(dc, window->glrc)) { 258 | ReleaseDC(window->handle, dc); 259 | LogReturn(, "Win32 OpenGL Window: Context Activation Failed"); 260 | } 261 | 262 | __LoadGLFunctions(v_wglGetProcAddress, _GetAddress); 263 | } 264 | 265 | ReleaseDC(window->handle, dc); 266 | 267 | } 268 | 269 | void B_BackendInit(OS_Window* _window) { 270 | B_BackendInitShared(_window, 0); 271 | } 272 | 273 | void B_BackendSelectRenderWindow(OS_Window* _window) { 274 | W32_Window* window = (W32_Window*) _window; 275 | HDC dc = GetDC(window->handle); 276 | v_wglMakeCurrent(dc, window->glrc); 277 | glViewport(0, 0, window->width, window->height); 278 | ReleaseDC(window->handle, dc); 279 | } 280 | 281 | void B_BackendSwapchainNext(OS_Window* _window) { 282 | W32_Window* window = (W32_Window*) _window; 283 | HDC dc = GetDC(window->handle); 284 | SwapBuffers(dc); 285 | ReleaseDC(window->handle, dc); 286 | glFlush(); 287 | } 288 | 289 | void B_BackendFree(OS_Window* _window) { 290 | W32_Window* window = (W32_Window*) _window; 291 | HDC dc = GetDC(window->handle); 292 | v_wglMakeCurrent(dc, 0); 293 | v_wglDeleteContext(window->glrc); 294 | ReleaseDC(window->handle, dc); 295 | } 296 | -------------------------------------------------------------------------------- /source/core/impl/win32_gl46_backend.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "gl_functions.h" 4 | #include "os/impl/win32_window.h" 5 | 6 | typedef i64 long_func(); 7 | typedef long_func* loader_func(const char* name); 8 | void __LoadGLFunctions(loader_func* load_proc, loader_func* fallback); 9 | 10 | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 11 | #define WGL_DRAW_TO_WINDOW_ARB 0x2001 12 | #define WGL_DRAW_TO_BITMAP_ARB 0x2002 13 | #define WGL_ACCELERATION_ARB 0x2003 14 | #define WGL_NEED_PALETTE_ARB 0x2004 15 | #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 16 | #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 17 | #define WGL_SWAP_METHOD_ARB 0x2007 18 | #define WGL_NUMBER_OVERLAYS_ARB 0x2008 19 | #define WGL_NUMBER_UNDERLAYS_ARB 0x2009 20 | #define WGL_TRANSPARENT_ARB 0x200A 21 | #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 22 | #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 23 | #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 24 | #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A 25 | #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B 26 | #define WGL_SHARE_DEPTH_ARB 0x200C 27 | #define WGL_SHARE_STENCIL_ARB 0x200D 28 | #define WGL_SHARE_ACCUM_ARB 0x200E 29 | #define WGL_SUPPORT_GDI_ARB 0x200F 30 | #define WGL_SUPPORT_OPENGL_ARB 0x2010 31 | #define WGL_DOUBLE_BUFFER_ARB 0x2011 32 | #define WGL_STEREO_ARB 0x2012 33 | #define WGL_PIXEL_TYPE_ARB 0x2013 34 | #define WGL_COLOR_BITS_ARB 0x2014 35 | #define WGL_RED_BITS_ARB 0x2015 36 | #define WGL_RED_SHIFT_ARB 0x2016 37 | #define WGL_GREEN_BITS_ARB 0x2017 38 | #define WGL_GREEN_SHIFT_ARB 0x2018 39 | #define WGL_BLUE_BITS_ARB 0x2019 40 | #define WGL_BLUE_SHIFT_ARB 0x201A 41 | #define WGL_ALPHA_BITS_ARB 0x201B 42 | #define WGL_ALPHA_SHIFT_ARB 0x201C 43 | #define WGL_ACCUM_BITS_ARB 0x201D 44 | #define WGL_ACCUM_RED_BITS_ARB 0x201E 45 | #define WGL_ACCUM_GREEN_BITS_ARB 0x201F 46 | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020 47 | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 48 | #define WGL_DEPTH_BITS_ARB 0x2022 49 | #define WGL_STENCIL_BITS_ARB 0x2023 50 | #define WGL_AUX_BUFFERS_ARB 0x2024 51 | #define WGL_NO_ACCELERATION_ARB 0x2025 52 | #define WGL_GENERIC_ACCELERATION_ARB 0x2026 53 | #define WGL_FULL_ACCELERATION_ARB 0x2027 54 | #define WGL_SWAP_EXCHANGE_ARB 0x2028 55 | #define WGL_SWAP_COPY_ARB 0x2029 56 | #define WGL_SWAP_UNDEFINED_ARB 0x202A 57 | #define WGL_TYPE_RGBA_ARB 0x202B 58 | #define WGL_TYPE_COLORINDEX_ARB 0x202C 59 | 60 | #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091 61 | #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092 62 | #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093 63 | #define WGL_CONTEXT_FLAGS_ARB 0x2094 64 | #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126 65 | #define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001 66 | #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002 67 | #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 68 | #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 69 | #define ERROR_INVALID_VERSION_ARB 0x2095 70 | #define ERROR_INVALID_PROFILE_ARB 0x2096 71 | 72 | typedef HGLRC WINAPI W32_wglCreateContext(HDC); 73 | typedef BOOL WINAPI W32_wglDeleteContext(HGLRC); 74 | typedef BOOL WINAPI W32_wglMakeCurrent(HDC, HGLRC); 75 | typedef PROC WINAPI W32_wglGetProcAddress(LPCSTR); 76 | 77 | typedef BOOL WINAPI W32_wglChoosePixelFormatARB(HDC hdc, const int* piAttribIList, const FLOAT* pfAttribFList, UINT nMaxFormats, int* piFormats, UINT* nNumFormats); 78 | typedef HGLRC WINAPI W32_wglCreateContextAttribsARB(HDC hdc, HGLRC hShareContext, const int* attribList); 79 | typedef BOOL WINAPI W32_wglSwapLayerBuffers(HDC hdc, UINT plane); 80 | 81 | static HMODULE opengl_module; 82 | 83 | static W32_wglCreateContext* v_wglCreateContext; 84 | 85 | static W32_wglDeleteContext* v_wglDeleteContext; 86 | static W32_wglMakeCurrent* v_wglMakeCurrent; 87 | static W32_wglGetProcAddress* v_wglGetProcAddress; 88 | static W32_wglChoosePixelFormatARB* v_wglChoosePixelFormatARB; 89 | static W32_wglCreateContextAttribsARB* v_wglCreateContextAttribsARB; 90 | 91 | void 92 | MessageCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void *userParam) { 93 | LogError("[GL46 Backend] OpenGL Error: %s", message); 94 | } 95 | 96 | long_func* _GetAddress(const char* name) { 97 | return (long_func*) GetProcAddress(opengl_module, name); 98 | } 99 | 100 | void B_BackendInitShared(OS_Window* _window, OS_Window* _share) { 101 | W32_Window* window = (W32_Window*) _window; 102 | W32_Window* share = (W32_Window*) _share; 103 | 104 | //- Load Preliminary WGL functions 105 | HINSTANCE hinstance = GetModuleHandle(0); 106 | 107 | if (!opengl_module || !v_wglCreateContext || !v_wglDeleteContext || !v_wglMakeCurrent || !v_wglGetProcAddress) { 108 | opengl_module = LoadLibraryA("opengl32.dll"); 109 | v_wglCreateContext = (W32_wglCreateContext*) GetProcAddress(opengl_module, "wglCreateContext"); 110 | if (!v_wglCreateContext) { 111 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglCreateContext failed"); 112 | } 113 | v_wglDeleteContext = (W32_wglDeleteContext*) GetProcAddress(opengl_module, "wglDeleteContext"); 114 | if (!v_wglDeleteContext) { 115 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglDeleteContext failed"); 116 | } 117 | v_wglMakeCurrent = (W32_wglMakeCurrent*) GetProcAddress(opengl_module, "wglMakeCurrent"); 118 | if (!v_wglMakeCurrent) { 119 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglMakeCurrent failed"); 120 | } 121 | v_wglGetProcAddress = (W32_wglGetProcAddress*) GetProcAddress(opengl_module, "wglGetProcAddress"); 122 | if (!v_wglGetProcAddress) { 123 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglGetProcAddress failed"); 124 | } 125 | } 126 | 127 | //- Create Dummy OpenGL Context 128 | if (!v_wglChoosePixelFormatARB || !v_wglCreateContextAttribsARB) { 129 | WNDCLASSA wc = { 130 | .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, 131 | .lpfnWndProc = DefWindowProcA, 132 | .hInstance = GetModuleHandle(0), 133 | .lpszClassName = "Dummy_WGL_weee", 134 | }; 135 | if (!RegisterClassA(&wc)) { 136 | LogReturn(, "Win32 OpenGL Window: New Class Registration failed"); 137 | } 138 | 139 | HWND bootstrap_window = CreateWindowExA( 140 | 0, 141 | wc.lpszClassName, 142 | "Dummy OpenGL Window", 143 | 0, 144 | CW_USEDEFAULT, 145 | CW_USEDEFAULT, 146 | CW_USEDEFAULT, 147 | CW_USEDEFAULT, 148 | 0, 149 | 0, 150 | wc.hInstance, 151 | 0); 152 | if (!bootstrap_window) { 153 | LogReturn(, "Win32 OpenGL Bootstrap: Window Creation Failed"); 154 | } 155 | 156 | HDC dc = GetDC(bootstrap_window); 157 | 158 | PIXELFORMATDESCRIPTOR format_desc = { 159 | .nSize = sizeof(PIXELFORMATDESCRIPTOR), 160 | .nVersion = 1, 161 | .iPixelType = PFD_TYPE_RGBA, 162 | .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 163 | .cColorBits = 32, 164 | .cAlphaBits = 8, 165 | .iLayerType = PFD_MAIN_PLANE, 166 | .cDepthBits = 24, 167 | .cStencilBits = 8, 168 | }; 169 | 170 | i32 format_idx = ChoosePixelFormat(dc, &format_desc); 171 | if (!format_idx) { 172 | ReleaseDC(bootstrap_window, dc); 173 | LogReturn(, "Win32 OpenGL Bootstrap: Choosing appropriate PixelFormat Failed"); 174 | } 175 | if (!SetPixelFormat(dc, format_idx, &format_desc)) { 176 | ReleaseDC(bootstrap_window, dc); 177 | LogReturn(, "Win32 OpenGL Bootstrap: Setting the PixelFormat Failed"); 178 | } 179 | 180 | HGLRC bootstrap_context = v_wglCreateContext(dc); 181 | if (!bootstrap_context) { 182 | ReleaseDC(bootstrap_window, dc); 183 | LogReturn(, "Win32 OpenGL Bootstrap: Context Creation Failed"); 184 | } 185 | if (!v_wglMakeCurrent(dc, bootstrap_context)) { 186 | ReleaseDC(window->handle, dc); 187 | LogReturn(, "Win32 OpenGL Bootstrap: Context Activation Failed"); 188 | } 189 | 190 | //- Load New ARB WGL functions using Dummy Context 191 | v_wglChoosePixelFormatARB = (W32_wglChoosePixelFormatARB*) v_wglGetProcAddress("wglChoosePixelFormatARB"); 192 | if (!v_wglChoosePixelFormatARB) { 193 | ReleaseDC(bootstrap_window, dc); 194 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglChoosePixelFormatARB failed"); 195 | } 196 | v_wglCreateContextAttribsARB = (W32_wglCreateContextAttribsARB*) v_wglGetProcAddress("wglCreateContextAttribsARB"); 197 | if (!v_wglCreateContextAttribsARB) { 198 | ReleaseDC(bootstrap_window, dc); 199 | LogReturn(, "Win32 OpenGL WGL Function Loading: Loading wglCreateContextAttribsARB failed"); 200 | } 201 | 202 | //- Delete Bootstrapping Stuff 203 | v_wglMakeCurrent(dc, 0); 204 | BOOL delete_context = v_wglDeleteContext(bootstrap_context); 205 | if (!delete_context) { 206 | LogReturn(, "Win32 OpenGL Bootstrap Window Destruction: Context Deletion Failed"); 207 | } 208 | ReleaseDC(bootstrap_window, dc); 209 | if (!DestroyWindow(bootstrap_window)) { 210 | LogReturn(, "Win32 OpenGL Bootstrap Window Destruction: Window Deletion Failed"); 211 | } 212 | UnregisterClassA("Dummy_WGL_weee", hinstance); 213 | } 214 | 215 | //- Create Actual Context 216 | HDC dc = GetDC(window->handle); 217 | int format_attribs_i[] = { 218 | WGL_DRAW_TO_WINDOW_ARB, true, 219 | WGL_SUPPORT_OPENGL_ARB, true, 220 | WGL_DOUBLE_BUFFER_ARB, true, 221 | WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, 222 | WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, 223 | WGL_COLOR_BITS_ARB, 32, 224 | WGL_DEPTH_BITS_ARB, 24, 225 | WGL_STENCIL_BITS_ARB, 8, 226 | 0 227 | }; 228 | 229 | int format_idx; 230 | UINT num_formats; 231 | v_wglChoosePixelFormatARB(dc, format_attribs_i, 0, 1, &format_idx, &num_formats); 232 | if (!num_formats) { 233 | ReleaseDC(window->handle, dc); 234 | LogReturn(, "Win32 OpenGL Window: Context Choosing Pixel Format failed"); 235 | } 236 | 237 | PIXELFORMATDESCRIPTOR format_desc = {0}; 238 | DescribePixelFormat(dc, format_idx, sizeof(PIXELFORMATDESCRIPTOR), &format_desc); 239 | if (!SetPixelFormat(dc, format_idx, &format_desc)) { 240 | ReleaseDC(window->handle, dc); 241 | LogReturn(, "Win32 OpenGL Window: Context SetPixelFormat failed"); 242 | } 243 | 244 | if (share) { 245 | window->glrc = share->glrc; 246 | } else { 247 | int context_attribs[] = { 248 | WGL_CONTEXT_MAJOR_VERSION_ARB, 4, 249 | WGL_CONTEXT_MINOR_VERSION_ARB, 6, 250 | WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 251 | #if defined(_DEBUG) 252 | WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_DEBUG_BIT_ARB, 253 | #endif 254 | 0, 255 | }; 256 | 257 | window->glrc = v_wglCreateContextAttribsARB(dc, 0, context_attribs); 258 | if (!window->glrc) { 259 | ReleaseDC(window->handle, dc); 260 | LogReturn(, "Win32 OpenGL Window: Context Creation Failed"); 261 | } 262 | if (!v_wglMakeCurrent(dc, window->glrc)) { 263 | ReleaseDC(window->handle, dc); 264 | LogReturn(, "Win32 OpenGL Window: Context Activation Failed"); 265 | } 266 | 267 | __LoadGLFunctions(v_wglGetProcAddress, _GetAddress); 268 | } 269 | 270 | glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 271 | glDebugMessageCallback(MessageCallback, nullptr); 272 | 273 | ReleaseDC(window->handle, dc); 274 | 275 | } 276 | 277 | void B_BackendInit(OS_Window* _window) { 278 | B_BackendInitShared(_window, 0); 279 | } 280 | 281 | void B_BackendSelectRenderWindow(OS_Window* _window) { 282 | W32_Window* window = (W32_Window*) _window; 283 | HDC dc = GetDC(window->handle); 284 | v_wglMakeCurrent(dc, window->glrc); 285 | glViewport(0, 0, window->width, window->height); 286 | ReleaseDC(window->handle, dc); 287 | } 288 | 289 | void B_BackendSwapchainNext(OS_Window* _window) { 290 | W32_Window* window = (W32_Window*) _window; 291 | HDC dc = GetDC(window->handle); 292 | SwapBuffers(dc); 293 | ReleaseDC(window->handle, dc); 294 | glFlush(); 295 | } 296 | 297 | void B_BackendFree(OS_Window* _window) { 298 | W32_Window* window = (W32_Window*) _window; 299 | HDC dc = GetDC(window->handle); 300 | v_wglMakeCurrent(dc, 0); 301 | v_wglDeleteContext(window->glrc); 302 | ReleaseDC(window->handle, dc); 303 | } 304 | -------------------------------------------------------------------------------- /source/core/resources.c: -------------------------------------------------------------------------------- 1 | #include "resources.h" 2 | #include "base/base.h" 3 | #include "os/os.h" 4 | 5 | 6 | #if defined(BACKEND_GL46) 7 | # include "impl/gl46_resources.c" 8 | 9 | #elif defined(BACKEND_GL33) 10 | # include "impl/gl33_resources.c" 11 | 12 | #elif defined(BACKEND_D3D11) 13 | # include "impl/d3d11_resources.c" 14 | 15 | #endif 16 | 17 | void R_Texture2DWhite(R_Texture2D* texture) { 18 | u8 data[] = { 255, 255, 255, 255 }; 19 | R_Texture2DAlloc(texture, TextureFormat_RGBA, 1, 1, TextureResize_Nearest, TextureResize_Nearest, TextureWrap_ClampToEdge, TextureWrap_ClampToEdge, TextureMutability_Immutable, TextureUsage_ShaderResource, data); 20 | } 21 | -------------------------------------------------------------------------------- /source/core/resources.h: -------------------------------------------------------------------------------- 1 | /* date = July 3rd 2022 0:06 pm */ 2 | 3 | #ifndef RESOURCES_H 4 | #define RESOURCES_H 5 | 6 | #include "defines.h" 7 | #include "base/str.h" 8 | #include "base/ds.h" 9 | #include "base/vmath.h" 10 | #include "os/window.h" 11 | 12 | 13 | //~ Enums 14 | typedef u32 R_BufferFlags; 15 | enum { 16 | BufferFlag_Dynamic = 0x1, 17 | 18 | // Enable only one of these 19 | BufferFlag_Type_Vertex = 0x2, 20 | BufferFlag_Type_Index = 0x4, 21 | }; 22 | 23 | typedef u32 R_ShaderType; 24 | enum { 25 | ShaderType_NULL, 26 | 27 | ShaderType_Vertex, 28 | ShaderType_Fragment, 29 | ShaderType_Geometry, 30 | 31 | ShaderType_MAX, 32 | }; 33 | 34 | typedef u32 R_InputAssembly; 35 | enum { 36 | InputAssembly_Triangles, 37 | InputAssembly_Lines, 38 | 39 | InputAssembly_MAX, 40 | }; 41 | 42 | typedef u32 R_AttributeType; 43 | enum { 44 | AttributeType_Float1, 45 | AttributeType_Float2, 46 | AttributeType_Float3, 47 | AttributeType_Float4, 48 | AttributeType_Integer1, 49 | AttributeType_Integer2, 50 | AttributeType_Integer3, 51 | AttributeType_Integer4, 52 | 53 | AttributeType_MAX, 54 | }; 55 | 56 | typedef struct R_Attribute { 57 | string name; 58 | R_AttributeType type; 59 | } R_Attribute; 60 | 61 | typedef u32 R_BlendMode; 62 | enum { 63 | BlendMode_None, 64 | BlendMode_Alpha, 65 | 66 | BlendMode_MAX, 67 | }; 68 | 69 | typedef u32 R_TextureWrapParam; 70 | enum { 71 | TextureWrap_ClampToEdge, 72 | TextureWrap_ClampToBorder, 73 | TextureWrap_Repeat, 74 | TextureWrap_MirroredRepeat, 75 | TextureWrap_MirrorClampToEdge, 76 | 77 | TextureWrap_MAX 78 | }; 79 | 80 | typedef u32 R_TextureResizeParam; 81 | enum { 82 | TextureResize_Nearest, 83 | TextureResize_Linear, 84 | TextureResize_LinearMipmapLinear, 85 | TextureResize_LinearMipmapNearest, 86 | TextureResize_NearestMipmapLinear, 87 | TextureResize_NearestMipmapNearest, 88 | 89 | TextureResize_MAX, 90 | }; 91 | 92 | typedef u32 R_TextureFormat; 93 | enum { 94 | TextureFormat_Invalid, 95 | 96 | TextureFormat_RInteger, 97 | TextureFormat_R, 98 | TextureFormat_RG, 99 | TextureFormat_RGB, 100 | TextureFormat_RGBA, 101 | TextureFormat_DepthStencil, 102 | 103 | TextureFormat_MAX, 104 | }; 105 | 106 | typedef i32 R_TextureChannel; 107 | enum { 108 | TextureChannel_Zero, 109 | TextureChannel_One, 110 | TextureChannel_R, 111 | TextureChannel_G, 112 | TextureChannel_B, 113 | TextureChannel_A, 114 | TextureChannel_MAX, 115 | }; 116 | 117 | typedef u32 R_TextureMutability; 118 | enum { 119 | TextureMutability_Immutable, 120 | TextureMutability_Uncommon, 121 | TextureMutability_Dynamic, 122 | 123 | TextureMutability_MAX, 124 | }; 125 | 126 | typedef u32 R_TextureUsage; 127 | enum { 128 | TextureUsage_ShaderResource = 0x1, 129 | TextureUsage_Drawable = 0x2, 130 | }; 131 | 132 | typedef u32 R_BufferMask; 133 | enum { 134 | BufferMask_Color = 0x01, 135 | BufferMask_Depth = 0x02, 136 | BufferMask_Stencil = 0x04, 137 | }; 138 | 139 | //~ Backend specific structures 140 | #if defined(BACKEND_GL33) 141 | # include "impl/gl33_resources.h" 142 | #elif defined(BACKEND_GL46) 143 | # include "impl/gl46_resources.h" 144 | #elif defined(BACKEND_D3D11) 145 | # include "impl/d3d11_resources.h" 146 | #endif 147 | 148 | 149 | //~ Buffers 150 | void R_BufferAlloc(R_Buffer* buf, R_BufferFlags flags, u32 v_stride); 151 | void R_BufferData(R_Buffer* buf, u64 size, void* data); 152 | void R_BufferUpdate(R_Buffer* buf, u64 offset, u64 size, void* data); 153 | void R_BufferFree(R_Buffer* buf); 154 | 155 | void R_UniformBufferAlloc(R_UniformBuffer* buf, string name, string_array member_names, 156 | R_ShaderPack* pack, R_ShaderType type); 157 | void R_UniformBufferFree(R_UniformBuffer* buf); 158 | 159 | void R_UniformBufferSetMat4(R_UniformBuffer* buf, string name, mat4 mat); 160 | void R_UniformBufferSetInt(R_UniformBuffer* buf, string name, i32 val); 161 | void R_UniformBufferSetIntArray(R_UniformBuffer* buf, string name, i32* vals, u32 count); 162 | void R_UniformBufferSetFloat(R_UniformBuffer* buf, string name, f32 val); 163 | void R_UniformBufferSetVec4(R_UniformBuffer* buf, string name, vec4 val); 164 | 165 | //~ Shaders 166 | void R_ShaderAlloc(R_Shader* shader, string data, R_ShaderType type); 167 | void R_ShaderAllocLoad(R_Shader* shader, string fp, R_ShaderType type); 168 | void R_ShaderFree(R_Shader* shader); 169 | 170 | void R_ShaderPackAlloc(R_ShaderPack* pack, R_Shader* shaders, u32 shader_count); 171 | void R_ShaderPackAllocLoad(R_ShaderPack* pack, string fp_prefix); 172 | void R_ShaderPackFree(R_ShaderPack* pack); 173 | 174 | void R_ShaderPackUploadMat4(R_ShaderPack* pack, string name, mat4 mat); 175 | void R_ShaderPackUploadInt(R_ShaderPack* pack, string name, i32 val); 176 | void R_ShaderPackUploadIntArray(R_ShaderPack* pack, string name, i32* vals, u32 count); 177 | void R_ShaderPackUploadFloat(R_ShaderPack* pack, string name, f32 val); 178 | void R_ShaderPackUploadVec4(R_ShaderPack* pack, string name, vec4 val); 179 | 180 | //~ Pipelines (VAOs OR NOT) 181 | void R_PipelineAlloc(R_Pipeline* in, R_InputAssembly assembly, R_Attribute* attributes, u32 attribute_count, R_ShaderPack* shader, R_BlendMode blending); 182 | void R_PipelineAddBuffer(R_Pipeline* in, R_Buffer* buf, u32 attribute_count); 183 | void R_PipelineAddUniformBuffer(R_Pipeline* in, R_UniformBuffer* buf); 184 | void R_PipelineBind(R_Pipeline* in); 185 | void R_PipelineFree(R_Pipeline* in); 186 | 187 | 188 | 189 | //~ Textures 190 | // NOTE(voxel): Consider converting to desc-style instead of this amount of args :pain: 191 | void R_Texture2DAlloc(R_Texture2D* texture, R_TextureFormat format, u32 width, u32 height, R_TextureResizeParam min, R_TextureResizeParam mag, R_TextureWrapParam wrap_s, R_TextureWrapParam wrap_t, R_TextureMutability mut, R_TextureUsage usage, void* initial_data); 192 | void R_Texture2DAllocLoad(R_Texture2D* texture, string filepath, R_TextureResizeParam min, R_TextureResizeParam mag, R_TextureWrapParam wrap_s, R_TextureWrapParam wrap_t, R_TextureMutability mut, R_TextureUsage usage); 193 | void R_Texture2DData(R_Texture2D* texture, void* data); 194 | void R_Texture2DWhite(R_Texture2D* texture); 195 | b8 R_Texture2DEquals(R_Texture2D* a, R_Texture2D* b); 196 | void R_Texture2DSwizzle(R_Texture2D* texture, i32* swizzles); 197 | void R_Texture2DBindTo(R_Texture2D* texture, u32 slot); 198 | void R_Texture2DFree(R_Texture2D* texture); 199 | 200 | 201 | //~ Framebuffer 202 | void R_FramebufferCreate(R_Framebuffer* framebuffer, u32 width, u32 height, R_Texture2D* color_attachments, u32 color_attachment_count, R_Texture2D depth_attachment); 203 | void R_FramebufferBind(R_Framebuffer* framebuffer); 204 | void R_FramebufferBindScreen(void); 205 | void R_FramebufferBlitToScreen(OS_Window* window, R_Framebuffer* framebuffer); 206 | void R_FramebufferReadPixel(R_Framebuffer* framebuffer, u32 attachment, u32 x, u32 y, 207 | void* data); 208 | void R_FramebufferResize(R_Framebuffer* framebuffer, u32 new_width, u32 new_height); 209 | void R_FramebufferFree(R_Framebuffer* framebuffer); 210 | 211 | 212 | void R_Clear(R_BufferMask buffer_mask); 213 | void R_ClearColor(f32 r, f32 g, f32 b, f32 a); 214 | void R_Viewport(i32 x, i32 y, i32 w, i32 h); 215 | void R_Draw(R_Pipeline* pipeline, u32 start, u32 count); 216 | 217 | #endif //RESOURCES_H 218 | -------------------------------------------------------------------------------- /source/defines.h: -------------------------------------------------------------------------------- 1 | /* date = September 27th 2021 11:48 am */ 2 | 3 | #ifndef DEFINES_H 4 | #define DEFINES_H 5 | 6 | #include 7 | 8 | // Unsigned int types. 9 | typedef unsigned char u8; 10 | typedef unsigned short u16; 11 | typedef unsigned int u32; 12 | typedef unsigned long long u64; 13 | 14 | // Signed int types. 15 | typedef signed char s8; 16 | typedef signed short s16; 17 | typedef signed int s32; 18 | typedef signed long long s64; 19 | 20 | // Regular int types. 21 | typedef char i8; 22 | typedef short i16; 23 | typedef int i32; 24 | typedef long long i64; 25 | 26 | // Floating point types 27 | typedef float f32; 28 | typedef double f64; 29 | 30 | // Boolean types 31 | typedef u8 b8; 32 | typedef u32 b32; 33 | 34 | // Void function type 35 | typedef void void_func(void); 36 | typedef void (*void_func_ptr)(void); 37 | 38 | #define true 1 39 | #define false 0 40 | 41 | #define null 0 42 | #define u32_max 4294967295 43 | 44 | #ifndef __cplusplus 45 | #define nullptr ((void*)0) 46 | #endif 47 | 48 | #if defined(__clang__) 49 | # define COMPILER_CLANG 50 | #elif defined(_MSC_VER) 51 | # define COMPILER_CL 52 | #elif defined(__GNUC__) 53 | # define COMPILER_GCC 54 | #endif 55 | 56 | #if defined(COMPILER_CLANG) 57 | # define FILE_NAME __FILE_NAME__ 58 | #else 59 | # define FILE_NAME __FILE__ 60 | #endif 61 | 62 | #define Statement(s) do {\ 63 | s\ 64 | } while (0) 65 | 66 | #define flush fflush(stdout) 67 | #define trace Statement(printf("%s:%d: Trace\n", FILE_NAME, __LINE__); flush;) 68 | #define unreachable Statement(\ 69 | printf("How did we get here? In %s on line %d\n", FILE_NAME, __LINE__);\ 70 | flush;\ 71 | ) 72 | 73 | #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) 74 | # define PLATFORM_WIN 75 | #elif defined(__linux__) || defined(__gnu_linux__) 76 | # define PLATFORM_LINUX 77 | #else 78 | # error "The codebase only supports windows and linux for now" 79 | #endif 80 | #define PATH_MAX 4096 81 | 82 | #ifdef PLATFORM_WIN 83 | # include 84 | # define get_cwd _getcwd 85 | #elif defined(PLATFORM_LINUX) 86 | # include 87 | # define get_cwd getcwd 88 | #endif 89 | 90 | // NOTE(voxel): Confirm gcc version works 91 | #if defined(COMPILER_CL) || defined(COMPILER_CLANG) 92 | # define dll_export __declspec(dllexport) 93 | # define dll_import __declspec(dllimport) 94 | #elif defined (COMPILER_GCC) 95 | # define dll_export __attribute__((dllexport)) 96 | # define dll_import __attribute__((dllimport)) 97 | #else 98 | # error dll_export not defined for this compiler 99 | #endif 100 | 101 | #ifdef IS_PLUGIN 102 | # define dll_plugin_api 103 | #else 104 | # define dll_plugin_api dll_export 105 | #endif 106 | 107 | #define Gigabytes(count) (u64) (count * 1024 * 1024 * 1024) 108 | #define Megabytes(count) (u64) (count * 1024 * 1024) 109 | #define Kilobytes(count) (u64) (count * 1024) 110 | 111 | #define Min(a,b) (((a)<(b))?(a):(b)) 112 | #define Max(a,b) (((a)>(b))?(a):(b)) 113 | #define Clamp(a,x,b) (((x)<(a))?(a):((b)<(x))?(b):(x)) 114 | #define ClampTop(a,b) Min(a,b) 115 | #define ClampBot(a,b) Max(a,b) 116 | #define ReverseClamp(a,x,b) (((x)<(a))?(b):((b)<(x))?(a):(x)) 117 | #define Wrap(a,x,b) ReverseClamp(a,x,b) 118 | 119 | #define MemoryCopy(d,s,z) memmove((d), (s), (z)) 120 | #define MemoryCopyStruct(d,s) MemoryCopy((d),(s), Min(sizeof(*(d)) , sizeof(*(s)))) 121 | #define MemoryZero(d,z) memset((d), 0, (z)) 122 | #define MemoryZeroStruct(d,s) MemoryZero((d),sizeof(s)) 123 | 124 | #define ArrayCount(a) (sizeof(a) / sizeof(a[0])) 125 | 126 | #define Slice_Prototype(type) typedef struct type##_slice { type* elems; u32 len; } type##_slice; 127 | #define slice(type) type##_slice 128 | 129 | #define Iterate(array, var) for (int var = 0; var < array.len; var++) 130 | #define IteratePtr(array, var) for (int var = 0; var < array->len; var++) 131 | 132 | // TODO(voxel): // TODO(voxel): 133 | // TODO(voxel): // TODO(voxel): 134 | // Add macros for Linked Lists 135 | 136 | #endif //DEFINES_H -------------------------------------------------------------------------------- /source/impl/ext.c: -------------------------------------------------------------------------------- 1 | #if defined(BACKEND_GL33) || defined(BACKEND_GL46) 2 | # include "core/impl/gl_functions.c" 3 | #elif defined(BACKEND_D3D11) 4 | # include "core/impl/d3d11_functions.c" 5 | #endif 6 | -------------------------------------------------------------------------------- /source/impl/stb_impl.c: -------------------------------------------------------------------------------- 1 | #define STB_IMAGE_IMPLEMENTATION 2 | #include 3 | 4 | #define STB_TRUETYPE_IMPLEMENTATION 5 | #include 6 | 7 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | #include "os/os.h" 3 | #include "os/window.h" 4 | #include "os/input.h" 5 | #include "base/tctx.h" 6 | #include "core/backend.h" 7 | #include "core/resources.h" 8 | 9 | #include "opt/ui.h" 10 | 11 | void MyResizeCallback(OS_Window* window, i32 w, i32 h) { 12 | // TODO(voxel): @awkward Add a "first resize" to Win32Window so that This if isn't required 13 | if (window->user_data) { 14 | R_Viewport(0, 0, w, h); 15 | UI_Resize((UI_Cache*) window->user_data, w, h); 16 | } 17 | } 18 | 19 | int main() { 20 | OS_Init(); 21 | 22 | ThreadContext context = {0}; 23 | tctx_init(&context); 24 | 25 | M_Arena global_arena; 26 | arena_init(&global_arena); 27 | 28 | U_FrameArenaInit(); 29 | 30 | OS_Window* window = OS_WindowCreate(1080, 720, str_lit("This should work")); 31 | window->resize_callback = MyResizeCallback; 32 | 33 | B_BackendInit(window); 34 | OS_WindowShow(window); 35 | 36 | UI_Cache* ui_cache = arena_alloc(&global_arena, sizeof(UI_Cache)); 37 | UI_Init(window, ui_cache); 38 | window->user_data = ui_cache; 39 | 40 | f32 start = 0.f; f32 end = 0.016f; 41 | f32 delta = 0.016f; 42 | i32 show_btn = 0; 43 | 44 | while (OS_WindowIsOpen(window)) { 45 | delta = end - start; 46 | start = OS_TimeMicrosecondsNow(); 47 | 48 | U_ResetFrameArena(); 49 | OS_PollEvents(); 50 | 51 | R_Clear(BufferMask_Color); 52 | UI_BeginFrame(window, ui_cache); 53 | 54 | UI_PrefWidth(ui_cache, UI_Percentage(100)) 55 | UI_PrefHeight(ui_cache, UI_Percentage(100)) 56 | UI_LayoutAxis(ui_cache, axis2_x) 57 | { 58 | UI_Box* full_container = UI_BoxMake(ui_cache, BoxFlag_DrawBackground | BoxFlag_DrawBorder | BoxFlag_Clip, str_lit("foo")); 59 | UI_Parent(ui_cache, full_container) { 60 | UI_Spacer(ui_cache, UI_Percentage(35)); 61 | 62 | UI_LayoutAxis(ui_cache, axis2_y) 63 | UI_PrefWidth(ui_cache, UI_Percentage(30)) 64 | UI_PrefHeight(ui_cache, UI_Percentage(100)) { 65 | UI_Box* vert = UI_BoxMake(ui_cache, BoxFlag_DrawBorder | 0, str_lit("VerticalCheckboxContainer")); 66 | 67 | UI_Parent(ui_cache, vert) 68 | UI_PrefWidth(ui_cache, UI_Percentage(100)) 69 | UI_PrefHeight(ui_cache, UI_Pixels(35)) 70 | UI_LayoutAxis(ui_cache, axis2_x) { 71 | UI_Box* pm = UI_BoxMake(ui_cache, 0, str_lit("PlusMinusContainer")); 72 | 73 | UI_Parent(ui_cache, pm) 74 | UI_PrefWidth(ui_cache, UI_Percentage(50)) 75 | UI_PrefHeight(ui_cache, UI_Pixels(35)){ 76 | if (UI_Button(ui_cache, str_lit("+##AddCheckbox")).clicked) 77 | show_btn ++; 78 | if (UI_Button(ui_cache, str_lit("-##SubCheckbox")).clicked) 79 | show_btn --; 80 | if (show_btn < 0) show_btn = 0; 81 | } 82 | 83 | UI_Spacer(ui_cache, UI_Pixels(15)); 84 | 85 | UI_ActiveColor(ui_cache, 0x9A5EBDFF) { 86 | for (i32 i = show_btn; i > 0; i--) 87 | UI_CheckboxF(ui_cache, "Checkbox##%d", i); 88 | } 89 | } 90 | 91 | } 92 | } 93 | } 94 | 95 | UI_EndFrame(ui_cache, delta / 1e6); 96 | 97 | B_BackendSwapchainNext(window); 98 | 99 | end = OS_TimeMicrosecondsNow(); 100 | } 101 | 102 | B_BackendFree(window); 103 | 104 | OS_WindowClose(window); 105 | 106 | U_FrameArenaFree(); 107 | arena_free(&global_arena); 108 | tctx_free(&context); 109 | } 110 | -------------------------------------------------------------------------------- /source/opt/meta/ui_stacks.c: -------------------------------------------------------------------------------- 1 | // This file is autogenerated from the corresponding .mdesk file 2 | 3 | UI_Box* UI_ParentPeek(UI_Cache* cache) { return *(cache->parent_stack.top-1); } 4 | UI_FontInfo* UI_FontPeek(UI_Cache* cache) { return *(cache->font_stack.top-1); } 5 | u32 UI_BoxColorPeek(UI_Cache* cache) { return *(cache->bg_color_stack.top-1); } 6 | u32 UI_HotColorPeek(UI_Cache* cache) { return *(cache->hot_color_stack.top-1); } 7 | u32 UI_ActiveColorPeek(UI_Cache* cache) { return *(cache->active_color_stack.top-1); } 8 | f32 UI_RoundingPeek(UI_Cache* cache) { return *(cache->rounding_stack.top-1); } 9 | f32 UI_EdgeSoftnessPeek(UI_Cache* cache) { return *(cache->softness_stack.top-1); } 10 | f32 UI_EdgeSizePeek(UI_Cache* cache) { return *(cache->edge_size_stack.top-1); } 11 | u32 UI_EdgeColorPeek(UI_Cache* cache) { return *(cache->edge_color_stack.top-1); } 12 | u32 UI_TextColorPeek(UI_Cache* cache) { return *(cache->text_color_stack.top-1); } 13 | UI_Size UI_PrefWidthPeek(UI_Cache* cache) { return *(cache->pref_width_stack.top-1); } 14 | UI_Size UI_PrefHeightPeek(UI_Cache* cache) { return *(cache->pref_height_stack.top-1); } 15 | axis2 UI_LayoutAxisPeek(UI_Cache* cache) { return *(cache->layout_axis_stack.top-1); } 16 | UI_RenderFunction* UI_CustomRenderFunctionPeek(UI_Cache* cache) { return *(cache->render_function_stack.top-1); } 17 | rect UI_ClippingRectPeek(UI_Cache* cache) { return *(cache->clipping_rect_stack.top-1); } 18 | 19 | UI_Box* UI_ParentPush(UI_Cache* cache, UI_Box* parent) { cache->parent_stack.len++; *cache->parent_stack.top=parent; cache->parent_stack.top++; return parent; } 20 | UI_FontInfo* UI_FontPush(UI_Cache* cache, UI_FontInfo* font) { cache->font_stack.len++; *cache->font_stack.top=font; cache->font_stack.top++; return font; } 21 | u32 UI_BoxColorPush(UI_Cache* cache, u32 bg_color) { cache->bg_color_stack.len++; *cache->bg_color_stack.top=bg_color; cache->bg_color_stack.top++; return bg_color; } 22 | u32 UI_HotColorPush(UI_Cache* cache, u32 hot_color) { cache->hot_color_stack.len++; *cache->hot_color_stack.top=hot_color; cache->hot_color_stack.top++; return hot_color; } 23 | u32 UI_ActiveColorPush(UI_Cache* cache, u32 active_color) { cache->active_color_stack.len++; *cache->active_color_stack.top=active_color; cache->active_color_stack.top++; return active_color; } 24 | f32 UI_RoundingPush(UI_Cache* cache, f32 rounding) { cache->rounding_stack.len++; *cache->rounding_stack.top=rounding; cache->rounding_stack.top++; return rounding; } 25 | f32 UI_EdgeSoftnessPush(UI_Cache* cache, f32 softness) { cache->softness_stack.len++; *cache->softness_stack.top=softness; cache->softness_stack.top++; return softness; } 26 | f32 UI_EdgeSizePush(UI_Cache* cache, f32 edge_size) { cache->edge_size_stack.len++; *cache->edge_size_stack.top=edge_size; cache->edge_size_stack.top++; return edge_size; } 27 | u32 UI_EdgeColorPush(UI_Cache* cache, u32 edge_color) { cache->edge_color_stack.len++; *cache->edge_color_stack.top=edge_color; cache->edge_color_stack.top++; return edge_color; } 28 | u32 UI_TextColorPush(UI_Cache* cache, u32 text_color) { cache->text_color_stack.len++; *cache->text_color_stack.top=text_color; cache->text_color_stack.top++; return text_color; } 29 | UI_Size UI_PrefWidthPush(UI_Cache* cache, UI_Size pref_width) { cache->pref_width_stack.len++; *cache->pref_width_stack.top=pref_width; cache->pref_width_stack.top++; return pref_width; } 30 | UI_Size UI_PrefHeightPush(UI_Cache* cache, UI_Size pref_height) { cache->pref_height_stack.len++; *cache->pref_height_stack.top=pref_height; cache->pref_height_stack.top++; return pref_height; } 31 | axis2 UI_LayoutAxisPush(UI_Cache* cache, axis2 layout_axis) { cache->layout_axis_stack.len++; *cache->layout_axis_stack.top=layout_axis; cache->layout_axis_stack.top++; return layout_axis; } 32 | UI_RenderFunction* UI_CustomRenderFunctionPush(UI_Cache* cache, UI_RenderFunction* render_function) { cache->render_function_stack.len++; *cache->render_function_stack.top=render_function; cache->render_function_stack.top++; return render_function; } 33 | rect UI_ClippingRectPush(UI_Cache* cache, rect clipping_rect) { cache->clipping_rect_stack.len++; *cache->clipping_rect_stack.top=clipping_rect; cache->clipping_rect_stack.top++; return clipping_rect; } 34 | 35 | UI_Box* UI_ParentSetNext(UI_Cache* cache, UI_Box* parent) { *cache->parent_stack.top=parent; cache->parent_stack.top++; cache->parent_stack.auto_pop=true; return parent; } 36 | UI_FontInfo* UI_FontSetNext(UI_Cache* cache, UI_FontInfo* font) { *cache->font_stack.top=font; cache->font_stack.top++; cache->font_stack.auto_pop=true; return font; } 37 | u32 UI_BoxColorSetNext(UI_Cache* cache, u32 bg_color) { *cache->bg_color_stack.top=bg_color; cache->bg_color_stack.top++; cache->bg_color_stack.auto_pop=true; return bg_color; } 38 | u32 UI_HotColorSetNext(UI_Cache* cache, u32 hot_color) { *cache->hot_color_stack.top=hot_color; cache->hot_color_stack.top++; cache->hot_color_stack.auto_pop=true; return hot_color; } 39 | u32 UI_ActiveColorSetNext(UI_Cache* cache, u32 active_color) { *cache->active_color_stack.top=active_color; cache->active_color_stack.top++; cache->active_color_stack.auto_pop=true; return active_color; } 40 | f32 UI_RoundingSetNext(UI_Cache* cache, f32 rounding) { *cache->rounding_stack.top=rounding; cache->rounding_stack.top++; cache->rounding_stack.auto_pop=true; return rounding; } 41 | f32 UI_EdgeSoftnessSetNext(UI_Cache* cache, f32 softness) { *cache->softness_stack.top=softness; cache->softness_stack.top++; cache->softness_stack.auto_pop=true; return softness; } 42 | f32 UI_EdgeSizeSetNext(UI_Cache* cache, f32 edge_size) { *cache->edge_size_stack.top=edge_size; cache->edge_size_stack.top++; cache->edge_size_stack.auto_pop=true; return edge_size; } 43 | u32 UI_EdgeColorSetNext(UI_Cache* cache, u32 edge_color) { *cache->edge_color_stack.top=edge_color; cache->edge_color_stack.top++; cache->edge_color_stack.auto_pop=true; return edge_color; } 44 | u32 UI_TextColorSetNext(UI_Cache* cache, u32 text_color) { *cache->text_color_stack.top=text_color; cache->text_color_stack.top++; cache->text_color_stack.auto_pop=true; return text_color; } 45 | UI_Size UI_PrefWidthSetNext(UI_Cache* cache, UI_Size pref_width) { *cache->pref_width_stack.top=pref_width; cache->pref_width_stack.top++; cache->pref_width_stack.auto_pop=true; return pref_width; } 46 | UI_Size UI_PrefHeightSetNext(UI_Cache* cache, UI_Size pref_height) { *cache->pref_height_stack.top=pref_height; cache->pref_height_stack.top++; cache->pref_height_stack.auto_pop=true; return pref_height; } 47 | axis2 UI_LayoutAxisSetNext(UI_Cache* cache, axis2 layout_axis) { *cache->layout_axis_stack.top=layout_axis; cache->layout_axis_stack.top++; cache->layout_axis_stack.auto_pop=true; return layout_axis; } 48 | UI_RenderFunction* UI_CustomRenderFunctionSetNext(UI_Cache* cache, UI_RenderFunction* render_function) { *cache->render_function_stack.top=render_function; cache->render_function_stack.top++; cache->render_function_stack.auto_pop=true; return render_function; } 49 | rect UI_ClippingRectSetNext(UI_Cache* cache, rect clipping_rect) { *cache->clipping_rect_stack.top=clipping_rect; cache->clipping_rect_stack.top++; cache->clipping_rect_stack.auto_pop=true; return clipping_rect; } 50 | 51 | UI_Box* UI_ParentPop(UI_Cache* cache) { cache->parent_stack.len--; cache->parent_stack.top--; return *cache->parent_stack.top; } 52 | UI_FontInfo* UI_FontPop(UI_Cache* cache) { cache->font_stack.len--; cache->font_stack.top--; return *cache->font_stack.top; } 53 | u32 UI_BoxColorPop(UI_Cache* cache) { cache->bg_color_stack.len--; cache->bg_color_stack.top--; return *cache->bg_color_stack.top; } 54 | u32 UI_HotColorPop(UI_Cache* cache) { cache->hot_color_stack.len--; cache->hot_color_stack.top--; return *cache->hot_color_stack.top; } 55 | u32 UI_ActiveColorPop(UI_Cache* cache) { cache->active_color_stack.len--; cache->active_color_stack.top--; return *cache->active_color_stack.top; } 56 | f32 UI_RoundingPop(UI_Cache* cache) { cache->rounding_stack.len--; cache->rounding_stack.top--; return *cache->rounding_stack.top; } 57 | f32 UI_EdgeSoftnessPop(UI_Cache* cache) { cache->softness_stack.len--; cache->softness_stack.top--; return *cache->softness_stack.top; } 58 | f32 UI_EdgeSizePop(UI_Cache* cache) { cache->edge_size_stack.len--; cache->edge_size_stack.top--; return *cache->edge_size_stack.top; } 59 | u32 UI_EdgeColorPop(UI_Cache* cache) { cache->edge_color_stack.len--; cache->edge_color_stack.top--; return *cache->edge_color_stack.top; } 60 | u32 UI_TextColorPop(UI_Cache* cache) { cache->text_color_stack.len--; cache->text_color_stack.top--; return *cache->text_color_stack.top; } 61 | UI_Size UI_PrefWidthPop(UI_Cache* cache) { cache->pref_width_stack.len--; cache->pref_width_stack.top--; return *cache->pref_width_stack.top; } 62 | UI_Size UI_PrefHeightPop(UI_Cache* cache) { cache->pref_height_stack.len--; cache->pref_height_stack.top--; return *cache->pref_height_stack.top; } 63 | axis2 UI_LayoutAxisPop(UI_Cache* cache) { cache->layout_axis_stack.len--; cache->layout_axis_stack.top--; return *cache->layout_axis_stack.top; } 64 | UI_RenderFunction* UI_CustomRenderFunctionPop(UI_Cache* cache) { cache->render_function_stack.len--; cache->render_function_stack.top--; return *cache->render_function_stack.top; } 65 | rect UI_ClippingRectPop(UI_Cache* cache) { cache->clipping_rect_stack.len--; cache->clipping_rect_stack.top--; return *cache->clipping_rect_stack.top; } 66 | 67 | -------------------------------------------------------------------------------- /source/opt/meta/ui_stacks.mdesk: -------------------------------------------------------------------------------- 1 | @table(name, member, type) 2 | UI_Stacks: 3 | { 4 | { Parent, parent, `UI_Box*` } 5 | { Font, font, `UI_FontInfo*` } 6 | { BoxColor, bg_color, `u32` } 7 | { HotColor, hot_color, `u32` } 8 | { ActiveColor, active_color, `u32` } 9 | { Rounding, rounding, `f32` } 10 | { EdgeSoftness, softness, `f32` } 11 | { EdgeSize, edge_size, `f32` } 12 | { EdgeColor, edge_color, `u32` } 13 | { TextColor, text_color, `u32` } 14 | { PrefWidth, pref_width, `UI_Size` } 15 | { PrefHeight, pref_height, `UI_Size` } 16 | { LayoutAxis, layout_axis, `axis2` } 17 | { CustomRenderFunction, render_function, `UI_RenderFunction*` } 18 | { ClippingRect, clipping_rect, `rect` } 19 | } 20 | 21 | 22 | 23 | @generator 24 | StackDecls: 25 | { 26 | `#define UI_STACK_MAX 64` 27 | `#define UI_STACK_DECLS \\` 28 | `struct {\\` 29 | @expander(UI_Stacks) 30 | `struct { $(type) elems[UI_STACK_MAX]; $(type) *top; u64 len; b32 auto_pop; } $(member)_stack;\\` 31 | `}` 32 | } 33 | 34 | @generator 35 | PopAllStacksToOne: 36 | { 37 | `#define UI_POP_ALL_STACKS_TO_ONE \\` 38 | @expander(UI_Stacks) 39 | `{ ui_cache->$(member)_stack.top = &ui_cache->$(member)_stack.elems[1]; ui_cache->$(member)_stack.len = 1; }\\` 40 | `` 41 | } 42 | 43 | @generator 44 | AutoPopStacks: 45 | { 46 | `#define UI_AUTOPOP_IF_REQ \\` 47 | @expander(UI_Stacks) 48 | `if (ui_cache->$(member)_stack.auto_pop) { UI_$(name)Pop(ui_cache); ui_cache->$(member)_stack.auto_pop = false; }\\` 49 | } 50 | 51 | @generator 52 | InitStacks: 53 | { 54 | `#define UI_INIT_STACKS \\` 55 | @expander(UI_Stacks) { 56 | `{ ui_cache->$(member)_stack.top = ui_cache->$(member)_stack.elems;\\` 57 | ` ui_cache->$(member)_stack.len = 0; }\\` 58 | } 59 | } 60 | 61 | @generator 62 | NormalFunctionPrototypes: 63 | { 64 | @expander(UI_Stacks) 65 | `$(type) UI_$(name)Peek(UI_Cache* cache);` 66 | `` 67 | @expander(UI_Stacks) 68 | `$(type) UI_$(name)Push(UI_Cache* cache, $(type) $(member));` 69 | `` 70 | @expander(UI_Stacks) 71 | `$(type) UI_$(name)SetNext(UI_Cache* cache, $(type) $(member));` 72 | `` 73 | @expander(UI_Stacks) 74 | `$(type) UI_$(name)Pop(UI_Cache* cache);` 75 | } 76 | 77 | @generator(C) 78 | NormalFunctionImpls: 79 | { 80 | @expander(UI_Stacks) 81 | `$(type) UI_$(name)Peek(UI_Cache* cache) { return *(cache->$(member)_stack.top-1); }` 82 | `` 83 | @expander(UI_Stacks) 84 | `$(type) UI_$(name)Push(UI_Cache* cache, $(type) $(member)) { cache->$(member)_stack.len++; *cache->$(member)_stack.top=$(member); cache->$(member)_stack.top++; return $(member); }` 85 | `` 86 | @expander(UI_Stacks) 87 | `$(type) UI_$(name)SetNext(UI_Cache* cache, $(type) $(member)) { *cache->$(member)_stack.top=$(member); cache->$(member)_stack.top++; cache->$(member)_stack.auto_pop=true; return $(member); }` 88 | `` 89 | @expander(UI_Stacks) 90 | `$(type) UI_$(name)Pop(UI_Cache* cache) { cache->$(member)_stack.len--; cache->$(member)_stack.top--; return *cache->$(member)_stack.top; }` 91 | } 92 | 93 | @generator 94 | DeferLoops: 95 | { 96 | `#define UI_DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end))` 97 | @expander(UI_Stacks) 98 | `#define UI_$(name)(ui_cache, $(member)) UI_DeferLoop(UI_$(name)Push(ui_cache, $(member)), UI_$(name)Pop(ui_cache))` 99 | } 100 | -------------------------------------------------------------------------------- /source/opt/phys_2d.c: -------------------------------------------------------------------------------- 1 | #include "phys_2d.h" 2 | 3 | #include "base/ds.h" 4 | 5 | DArray_Prototype(vec2); 6 | DArray_Impl(vec2); 7 | 8 | Slice_Prototype(vec2); 9 | 10 | typedef struct P2D_EPA_Edge { 11 | vec2 normal; 12 | f32 distance; 13 | u32 index; 14 | } P2D_EPA_Edge; 15 | 16 | static vec2 P2D_GJK_FurthestPoint(P2D_Collider* c, vec2 d) { 17 | switch (c->type) { 18 | case ColliderType_Polygon: { 19 | vec2 furthest_vert = {0}; 20 | f32 comparing_dot = 0; 21 | for (u32 i = 0; i < c->polygon.vert_count; i++) { 22 | vec2 c_to_vert = vec2_sub(c->polygon.vertices[i], c->center_pos); 23 | f32 dot = c_to_vert.x * d.x + c_to_vert.y * d.y; 24 | if (comparing_dot < dot) { 25 | comparing_dot = dot; 26 | furthest_vert = c->polygon.vertices[i]; 27 | } 28 | } 29 | return furthest_vert; 30 | } break; 31 | 32 | case ColliderType_Circle: { 33 | return vec2_add(c->center_pos, vec2_scale(d, c->circle.radius)); 34 | } break; 35 | } 36 | return (vec2) {0}; 37 | } 38 | 39 | static vec2 P2D_GJK_Support(P2D_Collider* a, P2D_Collider* b, vec2 d) { 40 | return vec2_sub( 41 | P2D_GJK_FurthestPoint(a, d), 42 | P2D_GJK_FurthestPoint(b, vec2_neg(d)) 43 | ); 44 | } 45 | 46 | static b8 P2D_GJK_HandleSimplex(darray(vec2)* simplex, vec2* d) { 47 | if (simplex->len == 2) { 48 | // Line case 49 | vec2 b = simplex->elems[0], a = simplex->elems[1]; 50 | vec2 ab = vec2_sub(b, a), ao = vec2_neg(a); 51 | vec2 ab_perp = vec2_normalize(vec2_triple_product(ab, ao, ab)); 52 | *d = ab_perp; 53 | return false; 54 | } else { 55 | // Triangle case 56 | vec2 c = simplex->elems[0], b = simplex->elems[1], a = simplex->elems[2]; 57 | vec2 ab = vec2_sub(b, a), ac = vec2_sub(c, a), ao = vec2_neg(a); 58 | vec2 ab_perp = vec2_normalize(vec2_triple_product(ac, ab, ab)); 59 | vec2 ac_perp = vec2_normalize(vec2_triple_product(ab, ac, ac)); 60 | if (vec2_dot(ab_perp, ao) < 0) { 61 | darray_remove(vec2, simplex, 0); 62 | *d = ab_perp; 63 | return false; 64 | } else if (vec2_dot(ac_perp, ao) < 0) { 65 | // erase B from simplex 66 | darray_remove(vec2, simplex, 1); 67 | *d = ac_perp; 68 | return false; 69 | } else return true; 70 | } 71 | return false; 72 | } 73 | 74 | static b8 P2D_EPA_IsWindingCounterClockwise(darray(vec2)* simplex) { 75 | f32 smn = 0; 76 | IteratePtr(simplex, i) { 77 | int j = i + 1 == simplex->len ? 0 : i + 1; 78 | vec2 a = simplex->elems[i]; 79 | vec2 b = simplex->elems[j]; 80 | 81 | smn += (b.x - a.x) * (b.y + a.y); 82 | } 83 | return smn > 0.f; 84 | } 85 | 86 | static P2D_EPA_Edge P2D_EPA_FindClosestEdge(darray(vec2)* simplex) { 87 | P2D_EPA_Edge res = {0}; 88 | res.distance = FLOAT_MAX; 89 | IteratePtr(simplex, i) { 90 | int j = i + 1 == simplex->len ? 0 : i + 1; 91 | vec2 a = simplex->elems[i]; 92 | if (a.x == 0 && a.y == 0) break; 93 | vec2 b = simplex->elems[j]; 94 | if (b.x == 0 && b.y == 0) break; 95 | 96 | vec2 e = vec2_sub(b, a); 97 | vec2 normal = { e.y, -e.x }; 98 | 99 | normal = vec2_normalize(normal); 100 | f32 d = vec2_dot(normal, a); 101 | 102 | if (d < res.distance) { 103 | res.distance = d; 104 | res.normal = normal; 105 | res.index = j; 106 | } 107 | } 108 | return res; 109 | } 110 | 111 | b8 P2D_CheckCollision(P2D_Collider* a, P2D_Collider* b) { 112 | vec2 d = vec2_sub(b->center_pos, a->center_pos); 113 | if (d.x || d.y) d = vec2_normalize(d); 114 | else d = (vec2) { 1, 0 }; 115 | 116 | darray(vec2) simplex = {0}; 117 | darray_reserve(vec2, &simplex, 3); 118 | darray_add(vec2, &simplex, P2D_GJK_Support(a, b, d)); 119 | 120 | d = vec2_normalize(vec2_neg(simplex.elems[0])); 121 | 122 | while (true) { 123 | vec2 A = P2D_GJK_Support(a, b, d); 124 | if (vec2_dot(A, d) <= 0) { 125 | darray_free(vec2, &simplex); 126 | return false; 127 | } 128 | darray_add(vec2, &simplex, A); 129 | if (P2D_GJK_HandleSimplex(&simplex, &d)) { 130 | darray_free(vec2, &simplex); 131 | return true; 132 | } 133 | } 134 | 135 | darray_free(vec2, &simplex); 136 | return false; 137 | } 138 | 139 | P2D_Collision P2D_GetCollision(P2D_Collider* a, P2D_Collider* b) { 140 | // GJK 141 | 142 | b8 colliding = false; 143 | vec2 resolution = {0}; 144 | 145 | vec2 d = vec2_sub(b->center_pos, a->center_pos); 146 | if (d.x || d.y) d = vec2_normalize(d); 147 | else d = (vec2) { 1, 0 }; 148 | 149 | darray(vec2) simplex = {0}; 150 | darray_reserve(vec2, &simplex, 3); 151 | darray_add(vec2, &simplex, P2D_GJK_Support(a, b, d)); 152 | 153 | d = vec2_normalize(vec2_neg(simplex.elems[0])); 154 | 155 | while (true) { 156 | vec2 A = P2D_GJK_Support(a, b, d); 157 | if (vec2_dot(A, d) <= 0) { 158 | colliding = false; 159 | break; 160 | } 161 | darray_add(vec2, &simplex, A); 162 | if (P2D_GJK_HandleSimplex(&simplex, &d)) { 163 | colliding = true; 164 | break; 165 | } 166 | } 167 | 168 | // EPA 169 | if (colliding) { 170 | vec2 min_normal = {0}; 171 | f32 min_distance = FLOAT_MAX; 172 | while (true) { 173 | P2D_EPA_Edge e = P2D_EPA_FindClosestEdge(&simplex); 174 | vec2 p = P2D_GJK_Support(a, b, e.normal); 175 | f32 d = vec2_dot(p, e.normal); 176 | 177 | if (d - e.distance < EPSILON) { 178 | min_normal = e.normal; 179 | min_distance = d; 180 | break; 181 | } else { 182 | darray_add_at(vec2, &simplex, p, e.index); 183 | } 184 | } 185 | resolution = vec2_scale(min_normal, min_distance + EPSILON); 186 | } 187 | 188 | darray_free(vec2, &simplex); 189 | 190 | return (P2D_Collision) { 191 | .is_colliding = colliding, 192 | .resolution = resolution, 193 | }; 194 | } 195 | 196 | P2D_Collider* P2D_ColliderAllocAARect(M_Arena* arena, rect r) { 197 | P2D_Collider* collider = arena_alloc(arena, sizeof(P2D_Collider)); 198 | collider->type = ColliderType_Polygon; 199 | collider->polygon.vertices = arena_alloc(arena, sizeof(vec2) * 4); 200 | collider->polygon.vert_count = 4; 201 | collider->polygon.vertices[0] = (vec2) { r.x, r.y }; 202 | collider->polygon.vertices[1] = (vec2) { r.x + r.w, r.y }; 203 | collider->polygon.vertices[2] = (vec2) { r.x + r.w, r.y + r.h }; 204 | collider->polygon.vertices[3] = (vec2) { r.x, r.y + r.h }; 205 | collider->center_pos = (vec2) { r.x + r.w / 2.f, r.y + r.h / 2.f }; 206 | return collider; 207 | } 208 | 209 | P2D_Collider* P2D_ColliderAllocRotatedRect(M_Arena* arena, rect r, f32 theta) { 210 | P2D_Collider* collider = arena_alloc(arena, sizeof(P2D_Collider)); 211 | collider->type = ColliderType_Polygon; 212 | collider->polygon.vertices = arena_alloc(arena, sizeof(vec2) * 4); 213 | collider->polygon.vert_count = 4; 214 | collider->polygon.vertices[0] = (vec2) { -r.w / 2.f, -r.h / 2.f }; 215 | collider->polygon.vertices[1] = (vec2) { r.w / 2.f, -r.h / 2.f }; 216 | collider->polygon.vertices[2] = (vec2) { r.w / 2.f, r.h / 2.f }; 217 | collider->polygon.vertices[3] = (vec2) { -r.w / 2.f, r.h / 2.f }; 218 | for (u32 i = 0; i < collider->polygon.vert_count; i++) { 219 | vec2 old = collider->polygon.vertices[i]; 220 | collider->polygon.vertices[i].x = r.x + r.w / 2.f + (cosf(theta) * old.x - sinf(theta) * old.y); 221 | collider->polygon.vertices[i].y = r.y + r.h / 2.f + (sinf(theta) * old.x + cosf(theta) * old.y); 222 | } 223 | collider->center_pos = (vec2) { r.x + r.w / 2.f, r.y + r.h / 2.f }; 224 | return collider; 225 | } 226 | 227 | P2D_Collider* P2D_ColliderAllocCircle(M_Arena* arena, vec2 c, f32 r) { 228 | P2D_Collider* collider = arena_alloc(arena, sizeof(P2D_Collider)); 229 | collider->type = ColliderType_Circle; 230 | collider->circle.radius = r; 231 | collider->center_pos = c; 232 | return collider; 233 | } 234 | 235 | void P2D_ColliderMoveTo(P2D_Collider* collider, vec2 new_pos) { 236 | switch (collider->type) { 237 | case ColliderType_Polygon: { 238 | for (u32 i = 0; i < collider->polygon.vert_count; i++) { 239 | collider->polygon.vertices[i] = vec2_add(new_pos, vec2_sub(collider->polygon.vertices[i], collider->center_pos)); 240 | } 241 | } break; 242 | } 243 | collider->center_pos = new_pos; 244 | } 245 | -------------------------------------------------------------------------------- /source/opt/phys_2d.h: -------------------------------------------------------------------------------- 1 | 2 | //~ 3 | // 4 | // PHYSICS_2D Optional Layer. 5 | // 6 | // 7 | // Collision Detection and resolution for arbitrary Convex Polygons and Circles. 8 | // A lot more to add here but other stuff is more important 9 | // 10 | //~ 11 | 12 | /* date = September 10th 2022 9:50 pm */ 13 | 14 | #ifndef PHYS_2D_H 15 | #define PHYS_2D_H 16 | 17 | #include "defines.h" 18 | #include "base/vmath.h" 19 | #include "base/mem.h" 20 | 21 | typedef u32 P2D_ColliderType; 22 | enum { 23 | ColliderType_Invalid, 24 | ColliderType_Polygon, 25 | ColliderType_Circle, 26 | ColliderType_MAX, 27 | }; 28 | 29 | typedef struct P2D_Collider { 30 | P2D_ColliderType type; 31 | 32 | vec2 center_pos; 33 | 34 | union { 35 | struct { f32 radius; } circle; 36 | struct { vec2* vertices; u32 vert_count; } polygon; 37 | }; 38 | } P2D_Collider; 39 | 40 | typedef struct P2D_Collision { 41 | vec2 resolution; 42 | b8 is_colliding; 43 | } P2D_Collision; 44 | 45 | b8 P2D_CheckCollision(P2D_Collider* a, P2D_Collider* b); 46 | P2D_Collision P2D_GetCollision(P2D_Collider* a, P2D_Collider* b); 47 | 48 | P2D_Collider* P2D_ColliderAllocAARect(M_Arena* arena, rect r); 49 | P2D_Collider* P2D_ColliderAllocRotatedRect(M_Arena* arena, rect r, f32 theta); 50 | P2D_Collider* P2D_ColliderAllocCircle(M_Arena* arena, vec2 c, f32 r); 51 | 52 | void P2D_ColliderMoveTo(P2D_Collider* collider, vec2 new_pos); 53 | 54 | #endif //PHYS_2D_H 55 | -------------------------------------------------------------------------------- /source/opt/render_2d.h: -------------------------------------------------------------------------------- 1 | 2 | //~ 3 | // 4 | // RENDER_2D Optional Layer. 5 | // NOTE(voxel): Currently does NOT work with the D3D11 Backend since Uniforms are not implemented 6 | // Simple 2D Immediate mode Rendering API. 7 | // 8 | // 9 | //~ 10 | 11 | /* date = July 20th 2022 9:08 pm */ 12 | 13 | #ifndef RENDER_2D_H 14 | #define RENDER_2D_H 15 | 16 | #include "defines.h" 17 | #include "base/base.h" 18 | #include "os/window.h" 19 | #include "core/resources.h" 20 | 21 | typedef struct R2D_Vertex { 22 | vec2 pos; 23 | vec2 tex_coords; 24 | f32 tex_index; 25 | vec4 color; 26 | } R2D_Vertex; 27 | 28 | #define R2D_MAX_INTERNAL_CACHE_VCOUNT 1024 29 | 30 | typedef struct R2D_VertexCache { 31 | R2D_Vertex* vertices; 32 | u32 count; 33 | u32 max_verts; 34 | } R2D_VertexCache; 35 | 36 | R2D_VertexCache R2D_VertexCacheCreate(M_Arena* arena, u32 max_verts); 37 | void R2D_VertexCacheReset(R2D_VertexCache* cache); 38 | b8 R2D_VertexCachePush(R2D_VertexCache* cache, R2D_Vertex* vertices, u32 vertex_count); 39 | 40 | typedef struct R2D_Batch { 41 | R2D_VertexCache cache; 42 | R_Texture2D *textures[8]; 43 | u8 tex_count; 44 | } R2D_Batch; 45 | 46 | DArray_Prototype(R2D_Batch); 47 | 48 | typedef struct R2D_Renderer { 49 | M_Arena arena; 50 | 51 | darray(R2D_Batch) batches; 52 | u8 current_batch; 53 | rect cull_quad; 54 | vec2 offset; 55 | 56 | R_Texture2D white_texture; 57 | R_Texture2D circle_texture; 58 | 59 | R_UniformBuffer constants; 60 | R_Pipeline pipeline; 61 | R_Buffer buffer; 62 | R_ShaderPack shader; 63 | } R2D_Renderer; 64 | 65 | void R2D_Init(OS_Window* window, R2D_Renderer* renderer); 66 | void R2D_Free(R2D_Renderer* renderer); 67 | void R2D_ResizeProjection(R2D_Renderer* renderer, vec2 render_size); 68 | 69 | void R2D_BeginDraw(R2D_Renderer* renderer); 70 | void R2D_EndDraw(R2D_Renderer* renderer); 71 | 72 | rect D_PushCullRect(R2D_Renderer* renderer, rect new_quad); 73 | void D_PopCullRect(R2D_Renderer* renderer, rect old_quad); 74 | vec2 D_PushOffset(R2D_Renderer* renderer, vec2 new_offset); 75 | void D_PopOffset(R2D_Renderer* renderer, vec2 old_offset); 76 | 77 | void R2D_DrawQuad(R2D_Renderer* renderer, rect quad, R_Texture2D* texture, rect uvs, vec4 color); 78 | void R2D_DrawQuadC(R2D_Renderer* renderer, rect quad, vec4 color); 79 | void R2D_DrawQuadT(R2D_Renderer* renderer, rect quad, R_Texture2D* texture, vec4 tint); 80 | void R2D_DrawQuadST(R2D_Renderer* renderer, rect quad, R_Texture2D* texture, rect uvs, vec4 tint); 81 | 82 | void R2D_DrawCircle(R2D_Renderer* renderer, vec2 pos, f32 radius, vec4 color); 83 | 84 | void R2D_DrawQuadRotated(R2D_Renderer* renderer, rect quad, R_Texture2D* texture, rect uvs, vec4 color, f32 theta); 85 | void R2D_DrawQuadRotatedC(R2D_Renderer* renderer, rect quad, vec4 color, f32 theta); 86 | void R2D_DrawQuadRotatedT(R2D_Renderer* renderer, rect quad, R_Texture2D* texture, vec4 tint, f32 theta); 87 | void R2D_DrawQuadRotatedST(R2D_Renderer* renderer, rect quad, R_Texture2D* texture, rect uvs, vec4 tint, f32 theta); 88 | 89 | void R2D_DrawPolygonWireframe(R2D_Renderer* renderer, vec2* verts, u32 vert_count, vec4 color); 90 | 91 | // NO CULLING FOR LINES 92 | void R2D_DrawLine(R2D_Renderer* renderer, vec2 start, vec2 end, f32 thickness, R_Texture2D* texture, rect uvs, vec4 color); 93 | void R2D_DrawLineC(R2D_Renderer* renderer, vec2 start, vec2 end, f32 thickness, vec4 color); 94 | 95 | #endif //RENDER_2D_H 96 | -------------------------------------------------------------------------------- /source/opt/ui.h: -------------------------------------------------------------------------------- 1 | /* date = March 1st 2023 6:37 pm */ 2 | 3 | //~ 4 | // 5 | // UI Optional Layer. 6 | // NOTE(voxel): Currently does NOT work with the D3D11 Backend since Uniforms are not implemented 7 | // 8 | // 9 | // Based on `https://www.rfleury.com/p/ui-series-table-of-contents` 10 | // Simple ImGUI API like 'Dear ImGui' by ocornut 11 | // 12 | //~ 13 | 14 | #ifndef UI_H 15 | #define UI_H 16 | 17 | #include "defines.h" 18 | #include "base/base.h" 19 | #include "os/window.h" 20 | #include "core/resources.h" 21 | 22 | #include 23 | 24 | //~ UI Text Caching Layer 25 | // TODO(voxel): Switch over from temporary STBTTF to Freetype. 26 | // TODO(voxel): Implement a Glyph Cache and Unicode stuff and things 27 | // TODO(voxel): It's quite tedious so for now I'll use stb-ttf 28 | 29 | typedef struct UI_FontInfo { 30 | R_Texture2D font_texture; 31 | stbtt_packedchar cdata[95]; 32 | f32 scale; 33 | f32 font_size; 34 | i32 ascent; 35 | i32 descent; 36 | i32 baseline; 37 | } UI_FontInfo; 38 | 39 | void UI_LoadFont(UI_FontInfo* fontinfo, string filepath, f32 size); 40 | f32 UI_GetStringSize(UI_FontInfo* fontinfo, string str); 41 | void UI_FreeFont(UI_FontInfo* fontinfo); 42 | 43 | //~ Main UI Layer 44 | 45 | //- UI Caching Helpers 46 | 47 | // not directly typedefed to u64 because it's possible more identification is required 48 | typedef struct UI_Key { 49 | u64 id; 50 | } UI_Key; 51 | 52 | UI_Key UI_KeyNull(void); 53 | UI_Key UI_KeyFromString(string s); 54 | b8 UI_KeyEquals(UI_Key a, UI_Key b); 55 | 56 | //- UI Layouting 57 | typedef u32 UI_SizeKind; 58 | enum { 59 | SizeKind_Null, 60 | SizeKind_Pixels, 61 | SizeKind_TextContent, 62 | SizeKind_PercentOfParent, 63 | SizeKind_ChildrenSum, 64 | }; 65 | 66 | typedef struct UI_Size { 67 | UI_SizeKind kind; 68 | f32 value; 69 | 70 | // NOTE(voxel): Supposedly required for handling violations 71 | //f32 strictness; 72 | } UI_Size; 73 | 74 | UI_Size UI_Pixels(f32 pixels); 75 | UI_Size UI_TextContent(f32 padding); 76 | UI_Size UI_Percentage(f32 pct); 77 | UI_Size UI_ChildrenSum(void); 78 | 79 | //- UI Colors 80 | 81 | typedef struct UI_QuadColorSet { 82 | u32 bl; // bottom left 83 | u32 br; // bottom right 84 | u32 tr; // top right 85 | u32 tl; // top left 86 | } UI_QuadColorSet; 87 | 88 | typedef struct UI_QuadVec4ColorSet { 89 | vec4 bl; // bottom left 90 | vec4 br; // bottom right 91 | vec4 tr; // top right 92 | vec4 tl; // top left 93 | } UI_QuadVec4ColorSet; 94 | 95 | inline static UI_QuadColorSet UI_QuadColorSetMake(u32 bl, u32 br, u32 tr, u32 tl) { 96 | return (UI_QuadColorSet) { bl, br, tr, tl }; 97 | } 98 | 99 | inline static UI_QuadVec4ColorSet UI_ColorToVec4Set(u32 color) { 100 | vec4 a = color_code_to_vec4(color); 101 | return (UI_QuadVec4ColorSet) { a, a, a, a }; 102 | } 103 | 104 | UI_QuadVec4ColorSet UI_ColorSetToVec4Set(UI_QuadColorSet set); 105 | UI_QuadVec4ColorSet UI_ColorSetLerp(UI_QuadVec4ColorSet* a, UI_QuadVec4ColorSet* b, f32 t); 106 | 107 | //- UI Box Things 108 | 109 | typedef struct UI_Cache UI_Cache; 110 | 111 | typedef u32 UI_BoxFlags; 112 | enum { 113 | BoxFlag_Clickable = 0x1, // @done 114 | BoxFlag_ViewScroll = 0x2, // TODO hard 115 | BoxFlag_DrawText = 0x4, // @done 116 | BoxFlag_DrawBorder = 0x8, // @done 117 | BoxFlag_DrawBackground = 0x10, // @done 118 | BoxFlag_DrawDropShadow = 0x20, // @done 119 | BoxFlag_Clip = 0x40, // @done 120 | BoxFlag_HotAnimation = 0x80, // @done 121 | BoxFlag_ActiveAnimation = 0x100, // @done 122 | BoxFlag_CustomRenderer = 0x200, // @done 123 | }; 124 | 125 | typedef struct UI_Box UI_Box; 126 | typedef void UI_RenderFunction(UI_Cache* cache, UI_Box* box); 127 | 128 | // n-ary tree node 129 | struct UI_Box { 130 | // Box tree is rebuilt each frame. 131 | UI_Box* parent; 132 | // sibling list 133 | UI_Box* prev; 134 | UI_Box* next; 135 | // children list 136 | UI_Box* first; 137 | UI_Box* last; 138 | 139 | // caching stuff 140 | UI_Box* hash_next; 141 | UI_Box* hash_prev; 142 | UI_Key key; 143 | u64 last_frame_touched_index; 144 | b32 direct_set; 145 | 146 | // main things 147 | UI_BoxFlags flags; 148 | string identifier; 149 | 150 | // input things 151 | b32 pressed_on_this; 152 | 153 | // layouting 154 | UI_Size semantic_size[axis2_count]; 155 | f32 computed_size[axis2_count]; 156 | axis2 layout_axis; 157 | f32 computed_rel_position[axis2_count]; 158 | rect target_bounds; 159 | rect bounds; 160 | rect clipped_bounds; 161 | 162 | // Properties!! 163 | f32 hot_t; 164 | u32 hot_color; 165 | f32 active_t; 166 | u32 active_color; 167 | b8 is_on; 168 | 169 | UI_FontInfo* font; 170 | u32 color; 171 | u32 edge_color; 172 | u32 text_color; 173 | f32 rounding; 174 | f32 softness; 175 | f32 edge_size; 176 | UI_RenderFunction* custom_render; 177 | }; 178 | 179 | UI_Box* UI_BoxMake(UI_Cache* cache, UI_BoxFlags flags, string str); 180 | UI_Box* UI_BoxMakeF(UI_Cache* cache, UI_BoxFlags flags, const char* fmt, ...); 181 | 182 | //- Stacks and Stacks of things 183 | #define UI_DeferLoop(begin, end) for(int _i_ = ((begin), 0); !_i_; _i_ += 1, (end)) 184 | 185 | #include "meta/ui_stacks.h" 186 | 187 | //~ UI Signals 188 | 189 | typedef struct UI_Signal { 190 | b8 clicked; // @done 191 | b8 double_clicked; // TODO 192 | b8 right_clicked; // @done 193 | b8 pressed; // @done 194 | b8 released; // @done 195 | b8 dragging; // TODO 196 | b8 hovering; // @done 197 | } UI_Signal; 198 | 199 | UI_Signal UI_SignalFromBox(UI_Box* box); 200 | 201 | //~ UI Rendering Layer 202 | // TODO(voxel): This exposed API will be for custom rendering procedures 203 | 204 | #define MAX_UI_QUADS 2048 205 | 206 | typedef struct UI_Vertex { 207 | // We get box size and center instead of vertex position, since vertex pos can be calculated 208 | // and box size/center cannot. Compression is being done basically 209 | vec2 box_size; 210 | vec2 box_center; 211 | vec2 uv; 212 | f32 tex_idx; 213 | vec4 color; 214 | vec4 clip_quad; 215 | vec3 rounding_softness_and_edge_size; 216 | } UI_Vertex; 217 | 218 | void UI_PushQuad(UI_Cache* ui_cache, rect bounds, rect uvs, R_Texture2D* texture, UI_QuadVec4ColorSet colors, f32 rounding, f32 softness, f32 edge_size); 219 | 220 | //~ UI Main Things 221 | 222 | // UI_Box* doesn't really work ;-; so let's just use u64 223 | // Some things about these macros are not nice, I really gotta make the names not tied to type again 224 | 225 | StableTable_Prototype(UI_Key, UI_Box); 226 | 227 | struct UI_Cache { 228 | stable_table(UI_Key, UI_Box) cache; 229 | 230 | M_Arena arena; 231 | 232 | UI_STACK_DECLS; 233 | 234 | UI_FontInfo default_font; 235 | 236 | UI_Box* root; 237 | u64 current_frame_index; 238 | 239 | UI_Key hot_key; 240 | UI_Key active_key; 241 | 242 | // Rendering stuff 243 | R_ShaderPack shaderpack; 244 | R_Pipeline pipeline; 245 | R_UniformBuffer constants; 246 | R_Buffer gpu_side_buffer; 247 | UI_Vertex cpu_side_buffer[MAX_UI_QUADS * 6]; 248 | u32 quad_count; 249 | R_Texture2D textures[8]; 250 | u32 textures_count; 251 | 252 | R_Texture2D white_texture; 253 | }; 254 | 255 | void UI_Init(OS_Window* window, UI_Cache* ui_cache); 256 | void UI_BeginFrame(OS_Window* window, UI_Cache* cache); 257 | void UI_EndFrame(UI_Cache* ui_cache, f32 delta_time); 258 | void UI_Free(UI_Cache* ui_cache); 259 | 260 | void UI_Resize(UI_Cache* ui_cache, i32 w, i32 h); 261 | void UI_ButtonEvent(UI_Cache* ui_cache, i32 button, i32 action); 262 | 263 | 264 | //~ UI Builder Layer 265 | 266 | UI_Signal UI_Button(UI_Cache* ui_cache, string id); 267 | UI_Signal UI_ButtonF(UI_Cache* ui_cache, const char* fmt, ...); 268 | b8 UI_Checkbox(UI_Cache* ui_cache, string id); 269 | b8 UI_CheckboxF(UI_Cache* ui_cache, const char* fmt, ...); 270 | void UI_Spacer(UI_Cache* ui_cache, UI_Size size); 271 | 272 | // TODO(voxel): A Lot more widgets to be added here 273 | 274 | #endif //UI_H 275 | -------------------------------------------------------------------------------- /source/os/impl/win32_key_code_translate.h: -------------------------------------------------------------------------------- 1 | /* date = July 15th 2022 7:50 pm */ 2 | 3 | #ifndef WIN32_KEY_CODES_H 4 | #define WIN32_KEY_CODES_H 5 | 6 | // No translation layer for win32 7 | 8 | #endif //WIN32_KEY_CODES_H 9 | -------------------------------------------------------------------------------- /source/os/impl/win32_window.c: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | #include "win32_window.h" 11 | #include "os/input.h" 12 | 13 | 14 | #include "core/impl/gl_functions.h" 15 | 16 | static void CALLBACK OS_PollEvents_Fiber(W32_Window* param); 17 | 18 | static char* _classname_buffer = {0}; 19 | static u32 _window_ct = 0; 20 | static b8 _should_close = false; 21 | static void* _main_fibre = 0; 22 | static void* _event_fibre = 0; 23 | 24 | static LRESULT CALLBACK Win32Proc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam); 25 | static void DefaultResizeCallback(OS_Window* _window, i32 w, i32 h); 26 | 27 | OS_Window* OS_WindowCreate(u32 width, u32 height, string title) { 28 | M_Scratch scratch = scratch_get(); 29 | 30 | HINSTANCE hinstance = GetModuleHandle(0); 31 | 32 | if (_window_ct == 0) { 33 | string prefix = str_lit("ClassOf_"); 34 | string final = str_cat(&scratch.arena, prefix, title); 35 | final = str_copy(&scratch.arena, final); 36 | _classname_buffer = calloc(final.size + 1, sizeof(char)); 37 | _classname_buffer = memmove(_classname_buffer, final.str, final.size + 1); 38 | 39 | WNDCLASSA wc = { 40 | .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, 41 | .lpfnWndProc = Win32Proc, 42 | .hInstance = hinstance, 43 | .hCursor = LoadCursor(0, IDC_ARROW), 44 | .hIcon = LoadIcon(0, IDI_APPLICATION), 45 | .lpszClassName = _classname_buffer, 46 | }; 47 | 48 | if (!RegisterClassA(&wc)) { 49 | LogReturn((OS_Window*) 0, "Win32 Window Class Registration Failed"); 50 | } 51 | } 52 | 53 | W32_Window* window = malloc(sizeof(W32_Window)); 54 | MemoryZeroStruct(window, W32_Window); 55 | window->width = width; 56 | window->height = height; 57 | window->title = title; 58 | 59 | RECT r = { 60 | .right = width, 61 | .bottom = height, 62 | }; 63 | DWORD window_style = WS_OVERLAPPEDWINDOW; 64 | AdjustWindowRect(&r, window_style, false); 65 | 66 | window->handle = CreateWindowExA(0, 67 | _classname_buffer, 68 | (const char*) title.str, 69 | window_style, 70 | CW_USEDEFAULT, 71 | CW_USEDEFAULT, 72 | r.right - r.left, 73 | r.bottom - r.top, 74 | 0, 75 | 0, 76 | hinstance, 77 | 0); 78 | 79 | 80 | if (_window_ct == 0) { 81 | _main_fibre = ConvertThreadToFiber(0); 82 | _event_fibre = CreateFiber(0, (LPFIBER_START_ROUTINE) OS_PollEvents_Fiber, &window); 83 | } 84 | SetWindowLongPtr(window->handle, GWLP_USERDATA, (LONG_PTR) window); 85 | 86 | if (!window->handle) { 87 | LogReturn((OS_Window*) 0, "Win32 Window Creation Failed"); 88 | } 89 | 90 | scratch_return(&scratch); 91 | 92 | _window_ct++; 93 | 94 | return (OS_Window*)window; 95 | } 96 | 97 | void OS_WindowShow(OS_Window* _window) { 98 | W32_Window* window = (W32_Window*) _window; 99 | ShowWindow(window->handle, true); 100 | UpdateWindow(window->handle); 101 | } 102 | 103 | // @seealso this function in x11_window.c for some notes 104 | void OS_WindowSetOpen(b8 open) { 105 | _should_close = !open; 106 | } 107 | 108 | b8 OS_WindowIsOpen(OS_Window* _window) { 109 | return !_should_close; 110 | } 111 | 112 | void OS_WindowClose(OS_Window* _window) { 113 | W32_Window* window = (W32_Window*) _window; 114 | DestroyWindow(window->handle); 115 | _window_ct--; 116 | if (_window_ct == 0) { 117 | UnregisterClass(_classname_buffer, GetModuleHandle(0)); 118 | free(_classname_buffer); 119 | } 120 | free(window); 121 | } 122 | 123 | static void CALLBACK OS_PollEvents_Fiber(W32_Window* param) { 124 | MSG _Msg = {0}; 125 | while (true) { 126 | if (PeekMessage(&_Msg, NULL, 0, 0, PM_REMOVE)) { 127 | TranslateMessage(&_Msg); 128 | DispatchMessage(&_Msg); 129 | } 130 | SwitchToFiber(_main_fibre); 131 | } 132 | } 133 | 134 | void OS_PollEvents(void) { 135 | __OS_InputReset(); 136 | SwitchToFiber(_event_fibre); 137 | } 138 | 139 | static void DefaultResizeCallback(OS_Window* _window, i32 w, i32 h) { 140 | W32_Window* window = (W32_Window*) _window; 141 | window->width = (u32)w; 142 | window->height = (u32)h; 143 | if (window->resize_callback) window->resize_callback(_window, w, h); 144 | } 145 | 146 | static LRESULT CALLBACK Win32Proc(HWND window, UINT msg, WPARAM wparam, LPARAM lparam) { 147 | LRESULT result = 0; 148 | 149 | OS_Window* os_window = (OS_Window*) GetWindowLongPtr(window, GWLP_USERDATA); 150 | 151 | switch (msg) { 152 | case WM_TIMER: { 153 | RECT r; 154 | GetClientRect(window, &r); 155 | int width = r.right - r.left; 156 | int height = r.bottom - r.top; 157 | 158 | DefaultResizeCallback(os_window, width, height); 159 | 160 | SwitchToFiber(_main_fibre); 161 | } break; 162 | 163 | case WM_ENTERSIZEMOVE: { 164 | SetTimer(window, 1, 1, 0); 165 | } break; 166 | 167 | case WM_EXITSIZEMOVE: { 168 | KillTimer(window, 1); 169 | 170 | RECT r; 171 | GetClientRect(window, &r); 172 | int width = r.right - r.left; 173 | int height = r.bottom - r.top; 174 | 175 | DefaultResizeCallback(os_window, width, height); 176 | } break; 177 | 178 | case WM_SIZE: { 179 | if (wparam == SIZE_MAXIMIZED || wparam == SIZE_RESTORED) { 180 | RECT r; 181 | GetClientRect(window, &r); 182 | int width = r.right - r.left; 183 | int height = r.bottom - r.top; 184 | 185 | DefaultResizeCallback(os_window, width, height); 186 | } 187 | } break; 188 | 189 | case WM_SYSKEYDOWN: 190 | case WM_KEYDOWN: { 191 | __OS_InputKeyCallback((u8)wparam, (lparam >> 30) & 0x01 ? Input_Repeat : Input_Press); 192 | if (os_window->key_callback) os_window->key_callback(os_window, (u8)wparam, (lparam >> 30) & 0x01 ? 193 | Input_Repeat : Input_Press); 194 | } break; 195 | 196 | case WM_SYSKEYUP: 197 | case WM_KEYUP: { 198 | __OS_InputKeyCallback((u8)wparam, Input_Release); 199 | if (os_window->key_callback) os_window->key_callback(os_window, (u8)wparam, Input_Release); 200 | } break; 201 | 202 | case WM_LBUTTONDOWN: 203 | case WM_MBUTTONDOWN: 204 | case WM_RBUTTONDOWN: { 205 | u8 btn = msg == WM_LBUTTONDOWN 206 | ? Input_MouseButton_Left : msg == WM_RBUTTONDOWN 207 | ? Input_MouseButton_Right : Input_MouseButton_Middle; 208 | 209 | __OS_InputButtonCallback(btn, Input_Press); 210 | if (os_window->button_callback) os_window->button_callback(os_window, btn, Input_Press); 211 | } break; 212 | 213 | case WM_LBUTTONUP: 214 | case WM_MBUTTONUP: 215 | case WM_RBUTTONUP: { 216 | u8 btn = msg == WM_LBUTTONUP 217 | ? Input_MouseButton_Left : msg == WM_RBUTTONUP 218 | ? Input_MouseButton_Right : Input_MouseButton_Middle; 219 | __OS_InputButtonCallback(btn, Input_Release); 220 | if (os_window->button_callback) os_window->button_callback(os_window, btn, Input_Release); 221 | } break; 222 | 223 | case WM_MOUSEMOVE: { 224 | __OS_InputCursorPosCallback((f32)GET_X_LPARAM(lparam), (f32)GET_Y_LPARAM(lparam)); 225 | } break; 226 | 227 | case WM_MOUSEWHEEL: { 228 | __OS_InputScrollCallback(0, (f32)GET_WHEEL_DELTA_WPARAM(wparam) / 120.f); 229 | } break; 230 | 231 | case WM_CLOSE: 232 | case WM_DESTROY: { 233 | PostQuitMessage(0); 234 | _should_close = true; 235 | } break; 236 | 237 | default: { 238 | result = DefWindowProcA(window, msg, wparam, lparam); 239 | } break; 240 | } 241 | 242 | return result; 243 | } 244 | -------------------------------------------------------------------------------- /source/os/impl/win32_window.h: -------------------------------------------------------------------------------- 1 | /* date = September 6th 2022 8:32 pm */ 2 | 3 | #ifndef WIN32_WINDOW_H 4 | #define WIN32_WINDOW_H 5 | 6 | #include "defines.h" 7 | 8 | #if defined(BACKEND_D3D11) 9 | # include 10 | # include 11 | #endif 12 | 13 | typedef struct W32_Window { 14 | u32 width; 15 | u32 height; 16 | string title; 17 | ResizeCallback* resize_callback; 18 | KeyCallback* key_callback; 19 | ButtonCallback* button_callback; 20 | void* user_data; 21 | HWND handle; 22 | 23 | #if defined(BACKEND_GL33) || defined(BACKEND_GL46) 24 | 25 | struct { 26 | HGLRC glrc; 27 | u64 v[6]; 28 | }; 29 | 30 | #elif defined(BACKEND_D3D11) 31 | 32 | struct { 33 | IDXGISwapChain* swapchain; 34 | ID3D11Device* device; 35 | ID3D11DeviceContext* context; 36 | ID3D11RenderTargetView* rtv; 37 | IDXGIInfoQueue* dbg_queue; 38 | u64 v[2]; 39 | }; 40 | 41 | #endif 42 | 43 | } W32_Window; 44 | 45 | #endif //WIN32_WINDOW_H 46 | -------------------------------------------------------------------------------- /source/os/impl/x11_key_code_translate.h: -------------------------------------------------------------------------------- 1 | /* date = April 19th 2023 4:12 pm */ 2 | 3 | #ifndef X11_KEY_CODES_H 4 | #define X11_KEY_CODES_H 5 | 6 | // https://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h 7 | 8 | #define X11Input_Key_LeftArrow 0xff51 9 | #define X11Input_Key_UpArrow 0xff52 10 | #define X11Input_Key_RightArrow 0xff53 11 | #define X11Input_Key_DownArrow 0xff54 12 | 13 | #define X11Input_Key_Minus 0x002d 14 | #define X11Input_Key_Equals 0x003d 15 | #define X11Input_Key_Backspace 0xff08 16 | 17 | #define X11Input_Key_Numpad0 0xffb0 18 | #define X11Input_Key_Numpad1 0xffb1 19 | #define X11Input_Key_Numpad2 0xffb2 20 | #define X11Input_Key_Numpad3 0xffb3 21 | #define X11Input_Key_Numpad4 0xffb4 22 | #define X11Input_Key_Numpad5 0xffb5 23 | #define X11Input_Key_Numpad6 0xffb6 24 | #define X11Input_Key_Numpad7 0xffb7 25 | #define X11Input_Key_Numpad8 0xffb8 26 | #define X11Input_Key_Numpad9 0xffb9 27 | #define X11Input_Key_NumpadPlus 0xffab 28 | #define X11Input_Key_NumpadMinus 0xffad 29 | #define X11Input_Key_NumpadStar 0xffaa 30 | #define X11Input_Key_NumpadSlash 0xffaf 31 | #define X11Input_Key_NumpadPeriod 0xffae 32 | 33 | #define X11Input_Key_LeftShift 0xffe1 34 | #define X11Input_Key_RightShift 0xffe2 35 | #define X11Input_Key_LeftControl 0xffe3 36 | #define X11Input_Key_RightControl 0xffe4 37 | #define X11Input_Key_LeftAlt 0xffe9 38 | #define X11Input_Key_RightAlt 0xffea 39 | #define X11Input_Key_CapsLock 0xffe5 40 | #define X11Input_Key_ScrollLock 0xff14 41 | #define X11Input_Key_NumLock 0xff7f 42 | #define X11Input_Key_Grave 0x0060 43 | #define X11Input_Key_Enter 0xff0d 44 | 45 | #define X11Input_Key_Period 0x002e 46 | #define X11Input_Key_Comma 0x002c 47 | #define X11Input_Key_ForwardSlash 0x002f 48 | #define X11Input_Key_BackSlash 0x005c 49 | #define X11Input_Key_Semicolon 0x003b 50 | #define X11Input_Key_Apostrophe 0x0027 51 | #define X11Input_Key_OpenBracket 0x005b 52 | #define X11Input_Key_CloseBracket 0x005d 53 | #define X11Input_Key_Escape 0xff1b 54 | #define X11Input_Key_Pause 0xff13 55 | 56 | #define X11Input_Key_F1 0xffbe 57 | #define X11Input_Key_F2 0xffbf 58 | #define X11Input_Key_F3 0xffc0 59 | #define X11Input_Key_F4 0xffc1 60 | #define X11Input_Key_F5 0xffc2 61 | #define X11Input_Key_F6 0xffc3 62 | #define X11Input_Key_F7 0xffc4 63 | #define X11Input_Key_F8 0xffc5 64 | #define X11Input_Key_F9 0xffc6 65 | #define X11Input_Key_F10 0xffc7 66 | #define X11Input_Key_F11 0xffc8 67 | #define X11Input_Key_F12 0xffc9 68 | 69 | #define X11Input_Key_PageUp 0xff55 70 | #define X11Input_Key_PageDown 0xff56 71 | #define X11Input_Key_End 0xff57 72 | #define X11Input_Key_Home 0xff50 73 | #define X11Input_Key_Insert 0xff63 74 | #define X11Input_Key_Delete 0xffff 75 | 76 | static inline u8 __X11KeyCode_Translate(u32 in) { 77 | if (in >= 'a' && in <= 'z') return in - 32; 78 | 79 | // is this smart? there HAS to be a better way 80 | switch (in) { 81 | case X11Input_Key_LeftArrow: return Input_Key_LeftArrow; 82 | case X11Input_Key_UpArrow: return Input_Key_UpArrow; 83 | case X11Input_Key_RightArrow: return Input_Key_RightArrow; 84 | case X11Input_Key_DownArrow: return Input_Key_DownArrow; 85 | case X11Input_Key_Minus: return Input_Key_Minus; 86 | case X11Input_Key_Equals: return Input_Key_Equals; 87 | case X11Input_Key_Backspace: return Input_Key_Backspace; 88 | case X11Input_Key_Numpad0: return Input_Key_Numpad0; 89 | case X11Input_Key_Numpad1: return Input_Key_Numpad1; 90 | case X11Input_Key_Numpad2: return Input_Key_Numpad2; 91 | case X11Input_Key_Numpad3: return Input_Key_Numpad3; 92 | case X11Input_Key_Numpad4: return Input_Key_Numpad4; 93 | case X11Input_Key_Numpad5: return Input_Key_Numpad5; 94 | case X11Input_Key_Numpad6: return Input_Key_Numpad6; 95 | case X11Input_Key_Numpad7: return Input_Key_Numpad7; 96 | case X11Input_Key_Numpad8: return Input_Key_Numpad8; 97 | case X11Input_Key_Numpad9: return Input_Key_Numpad9; 98 | case X11Input_Key_NumpadPlus: return Input_Key_NumpadPlus; 99 | case X11Input_Key_NumpadMinus: return Input_Key_NumpadMinus; 100 | case X11Input_Key_NumpadStar: return Input_Key_NumpadStar; 101 | case X11Input_Key_NumpadSlash: return Input_Key_NumpadSlash; 102 | case X11Input_Key_NumpadPeriod: return Input_Key_NumpadPeriod; 103 | case X11Input_Key_LeftShift: return Input_Key_LeftShift; 104 | case X11Input_Key_RightShift: return Input_Key_RightShift; 105 | case X11Input_Key_LeftControl: return Input_Key_LeftControl; 106 | case X11Input_Key_RightControl: return Input_Key_RightControl; 107 | case X11Input_Key_LeftAlt: return Input_Key_LeftAlt; 108 | case X11Input_Key_RightAlt: return Input_Key_RightAlt; 109 | case X11Input_Key_CapsLock: return Input_Key_CapsLock; 110 | case X11Input_Key_ScrollLock: return Input_Key_ScrollLock; 111 | case X11Input_Key_NumLock: return Input_Key_NumLock; 112 | case X11Input_Key_Grave: return Input_Key_Grave; 113 | case X11Input_Key_Enter: return Input_Key_Enter; 114 | case X11Input_Key_Period: return Input_Key_Period; 115 | case X11Input_Key_Comma: return Input_Key_Comma; 116 | case X11Input_Key_ForwardSlash: return Input_Key_ForwardSlash; 117 | case X11Input_Key_BackSlash: return Input_Key_BackSlash; 118 | case X11Input_Key_Semicolon: return Input_Key_Semicolon; 119 | case X11Input_Key_Apostrophe: return Input_Key_Apostrophe; 120 | case X11Input_Key_OpenBracket: return Input_Key_OpenBracket; 121 | case X11Input_Key_CloseBracket: return Input_Key_CloseBracket; 122 | case X11Input_Key_Escape: return Input_Key_Escape; 123 | case X11Input_Key_Pause: return Input_Key_Pause; 124 | case X11Input_Key_F1: return Input_Key_F1; 125 | case X11Input_Key_F2: return Input_Key_F2; 126 | case X11Input_Key_F3: return Input_Key_F3; 127 | case X11Input_Key_F4: return Input_Key_F4; 128 | case X11Input_Key_F5: return Input_Key_F5; 129 | case X11Input_Key_F6: return Input_Key_F6; 130 | case X11Input_Key_F7: return Input_Key_F7; 131 | case X11Input_Key_F8: return Input_Key_F8; 132 | case X11Input_Key_F9: return Input_Key_F9; 133 | case X11Input_Key_F10: return Input_Key_F10; 134 | case X11Input_Key_F11: return Input_Key_F11; 135 | case X11Input_Key_F12: return Input_Key_F12; 136 | case X11Input_Key_PageUp: return Input_Key_PageUp; 137 | case X11Input_Key_PageDown: return Input_Key_PageDown; 138 | case X11Input_Key_End: return Input_Key_End; 139 | case X11Input_Key_Home: return Input_Key_Home; 140 | case X11Input_Key_Insert: return Input_Key_Insert; 141 | case X11Input_Key_Delete: return Input_Key_Delete; 142 | } 143 | return in; 144 | } 145 | 146 | #endif //X11_KEY_CODES_H 147 | -------------------------------------------------------------------------------- /source/os/impl/x11_window.c: -------------------------------------------------------------------------------- 1 | #include "x11_window.h" 2 | #include 3 | 4 | #include "base/ds.h" 5 | #include "os/input.h" 6 | 7 | 8 | static u32 _window_ct = 0; 9 | static Display* _display; 10 | static i32 _screen; 11 | static b8 _should_close = false; 12 | 13 | // Sadly for event callbacks we need to have a hash table. 14 | typedef X11_Window* X11_WindowHandle; 15 | HashTable_Prototype(Window, X11_WindowHandle); 16 | 17 | b8 X11WindowHandleIsNull(Window w) { return w == 0; } 18 | b8 X11WindowHandlesAreEqual(Window a, Window b) { return a == b; } 19 | u64 X11WindowHash(Window w) { return (u64)w; } 20 | b8 OSWindowHandleIsNull(X11_WindowHandle w) { return (u64)w == 0; } 21 | b8 OSWindowHandleIsTomb(X11_WindowHandle w) { return (u64)w == 69; } 22 | HashTable_Impl(Window, X11_WindowHandle, X11WindowHandleIsNull, X11WindowHandlesAreEqual, 23 | X11WindowHash, (X11_WindowHandle)69, OSWindowHandleIsNull, OSWindowHandleIsTomb); 24 | 25 | hash_table(Window, X11_WindowHandle) _window_map; 26 | 27 | OS_Window* OS_WindowCreate(u32 width, u32 height, string title) { 28 | if (_window_ct == 0) { 29 | _display = XOpenDisplay(NULL); 30 | if (_display == NULL) { 31 | LogReturn((OS_Window*) 0, "X11 Window Display Opening Failed"); 32 | } 33 | XAutoRepeatOn(_display); 34 | _screen = DefaultScreen(_display); 35 | _window_ct += 1; 36 | hash_table_init(Window, X11_WindowHandle, &_window_map); 37 | } 38 | 39 | X11_Window* window = malloc(sizeof(X11_Window)); 40 | MemoryZeroStruct(window, X11_Window); 41 | window->width = width; 42 | window->height = height; 43 | window->title = title; 44 | window->display = _display; 45 | 46 | window->handle = 47 | XCreateSimpleWindow(_display, RootWindow(_display, _screen), 30, 30, width, height, 0, 0, 0); 48 | XSelectInput(_display, window->handle, 49 | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | 50 | PointerMotionMask | ResizeRedirectMask | ExposureMask); 51 | XStoreName(_display, window->handle, (char*)title.str); 52 | 53 | hash_table_set(Window, X11_WindowHandle, &_window_map, window->handle, window); 54 | 55 | return (OS_Window*) window; 56 | } 57 | 58 | void OS_WindowShow(OS_Window* _window) { 59 | X11_Window* window = (X11_Window*) _window; 60 | XMapWindow(_display, window->handle); 61 | } 62 | 63 | // NOTE(voxel): for now all windows share one state for being open or closed. 64 | // this should probably change but it's fine for now since I'm not doing 65 | // multiwindow applications 66 | // This is one specific place where a setter has to be used. It could mean different things in 67 | // different OS contexts since should_close is a static variable currently. 68 | // definitely should make this a per window thing but till then.... 69 | void OS_WindowSetOpen(b8 open) { 70 | _should_close = !open; 71 | } 72 | 73 | b8 OS_WindowIsOpen(OS_Window* _window) { 74 | return !_should_close; 75 | } 76 | 77 | // A full hash table fetch for EVERY SINGLE GODDAMN EVENT? 78 | // Maybe darrays are just going be better for this usecase 79 | 80 | void OS_PollEvents(void) { 81 | __OS_InputReset(); 82 | XEvent event; 83 | while (XPending(_display)) { 84 | XNextEvent(_display, &event); 85 | if (event.type == KeyPress) { 86 | KeySym k = XkbKeycodeToKeysym(_display, event.xkey.keycode, 0, 0); 87 | 88 | u8 translated = __X11KeyCode_Translate(k); 89 | X11_Window* window; 90 | hash_table_get(Window, X11_WindowHandle, &_window_map, event.xkey.window, &window); 91 | b8 did_repeat = __OS_InputKeyCallbackCheckRepeat(translated, Input_Press); 92 | 93 | if (window->key_callback) window->key_callback((OS_Window*) window, translated, did_repeat ? Input_Repeat : Input_Press); 94 | } else if (event.type == KeyRelease) { 95 | KeySym k = XkbKeycodeToKeysym(_display, event.xkey.keycode, 0, 0); 96 | 97 | if (XEventsQueued(_display, QueuedAfterReading)) { 98 | XEvent nev; 99 | XPeekEvent(_display, &nev); 100 | if (!(nev.type == KeyPress && nev.xkey.time == event.xkey.time && 101 | nev.xkey.keycode == event.xkey.keycode)) { 102 | u8 translated = __X11KeyCode_Translate(k); 103 | X11_Window* window; 104 | hash_table_get(Window, X11_WindowHandle, &_window_map, event.xkey.window, 105 | &window); 106 | __OS_InputKeyCallbackCheckRepeat(translated, Input_Release); 107 | if (window->key_callback) window->key_callback((OS_Window*) window, translated, Input_Release); 108 | } 109 | } else { 110 | 111 | u8 translated = __X11KeyCode_Translate(k); 112 | X11_Window* window; 113 | hash_table_get(Window, X11_WindowHandle, &_window_map, event.xkey.window, &window); 114 | __OS_InputKeyCallbackCheckRepeat(translated, Input_Release); 115 | if (window->key_callback) window->key_callback((OS_Window*) window, translated, Input_Release); 116 | } 117 | } else if (event.type == ButtonPress) { 118 | if (event.xbutton.button != 4 && event.xbutton.button != 5) { 119 | u8 translated = event.xbutton.button - 1; 120 | X11_Window* window; 121 | hash_table_get(Window, X11_WindowHandle, &_window_map, event.xbutton.window, &window); 122 | __OS_InputButtonCallback(translated, Input_Press); 123 | if (window->button_callback) window->button_callback((OS_Window*) window, translated, Input_Press); 124 | } else { 125 | f32 translated_delta = event.xbutton.button == 4 ? 1.f : -1.f; 126 | __OS_InputScrollCallback(0, translated_delta); 127 | } 128 | } else if (event.type == ButtonRelease) { 129 | if (event.xbutton.button != 4 && event.xbutton.button != 5) { 130 | u8 translated = event.xbutton.button - 1; 131 | X11_Window* window; 132 | hash_table_get(Window, X11_WindowHandle, &_window_map, event.xbutton.window, &window); 133 | __OS_InputButtonCallback(translated, Input_Release); 134 | if (window->button_callback) window->button_callback((OS_Window*) window, translated, Input_Release); 135 | } 136 | } else if (event.type == MotionNotify) { 137 | __OS_InputCursorPosCallback((f32)event.xmotion.x, (f32)event.xmotion.y); 138 | } else if (event.type == Expose) { 139 | X11_Window* window; 140 | hash_table_get(Window, X11_WindowHandle, &_window_map, event.xexpose.window, &window); 141 | if (window->resize_callback) window->resize_callback((OS_Window*) window, event.xexpose.width, event.xexpose.height); 142 | } 143 | } 144 | } 145 | 146 | void OS_WindowClose(OS_Window* _window) { 147 | X11_Window* window = (X11_Window*) _window; 148 | XDestroyWindow(_display, window->handle); 149 | _window_ct -= 1; 150 | 151 | if (!_window_ct) { 152 | XCloseDisplay(_display); 153 | hash_table_free(Window, X11_WindowHandle, &_window_map); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /source/os/impl/x11_window.h: -------------------------------------------------------------------------------- 1 | /* date = April 19th 2023 10:29 am */ 2 | 3 | #ifndef X11_WINDOW_H 4 | #define X11_WINDOW_H 5 | 6 | #include 7 | 8 | typedef XID GLXWindow; 9 | typedef XID GLXDrawable; 10 | typedef struct __GLXFBConfig* GLXFBConfig; 11 | typedef struct __GLXcontext* GLXContext; 12 | typedef void GLXextproc(void); 13 | 14 | typedef struct X11_Window { 15 | u32 width; 16 | u32 height; 17 | string title; 18 | ResizeCallback* resize_callback; 19 | KeyCallback* key_callback; 20 | ButtonCallback* button_callback; 21 | void* user_data; 22 | 23 | Display* display; 24 | Window handle; 25 | #if defined(BACKEND_GL33) || defined(BACKEND_GL46) 26 | struct { 27 | GLXContext gl_context; 28 | }; 29 | #endif 30 | } X11_Window; 31 | 32 | #endif //X11_WINDOW_H 33 | -------------------------------------------------------------------------------- /source/os/input.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | #include "base/base.h" 3 | 4 | #include "input.h" 5 | 6 | typedef struct OS_InputState { 7 | u8 key_frame_states[350]; 8 | u8 key_current_states[350]; 9 | u8 button_frame_states[8]; 10 | u8 button_current_states[8]; 11 | 12 | f32 mouse_x; 13 | f32 mouse_y; 14 | f32 mouse_scrollx; 15 | f32 mouse_scrolly; 16 | f32 mouse_absscrollx; 17 | f32 mouse_absscrolly; 18 | f32 mouse_recordedx; 19 | f32 mouse_recordedy; 20 | } OS_InputState; 21 | static OS_InputState _state; 22 | 23 | void __OS_InputKeyCallback(u8 key, i32 action) { 24 | //if (key < 0 || key >= 350) { 25 | //LogError("Unknown Key: %u", key); 26 | //return; 27 | //} 28 | 29 | switch (action) { 30 | case Input_Press: { 31 | _state.key_frame_states[key] = 0b00000001; 32 | _state.key_current_states[key] = 1; 33 | } break; 34 | 35 | case Input_Release: { 36 | _state.key_frame_states[key] = 0b00000010; 37 | _state.key_current_states[key] = 0; 38 | } break; 39 | 40 | case Input_Repeat: { 41 | _state.key_frame_states[key] = 0b00000100; 42 | } break; 43 | } 44 | } 45 | 46 | b8 __OS_InputKeyCallbackCheckRepeat(u8 key, i32 action) { 47 | //if (key < 0 || key >= 350) { 48 | //LogError("Unknown Key: %u", key); 49 | //return false; 50 | //} 51 | 52 | b8 did_repeat = false; 53 | if (action == Input_Press) { 54 | if (_state.key_current_states[key] == 1) { 55 | action = Input_Repeat; 56 | did_repeat = true; 57 | } 58 | } 59 | 60 | switch (action) { 61 | case Input_Press: { 62 | _state.key_frame_states[key] = 0b00000001; 63 | _state.key_current_states[key] = 1; 64 | } break; 65 | 66 | case Input_Release: { 67 | _state.key_frame_states[key] = 0b00000010; 68 | _state.key_current_states[key] = 0; 69 | } break; 70 | 71 | case Input_Repeat: { 72 | _state.key_frame_states[key] = 0b00000100; 73 | } break; 74 | } 75 | 76 | return did_repeat; 77 | } 78 | 79 | void __OS_InputButtonCallback(u8 button, int action) { 80 | if (button < 0 || button >= 8) return; 81 | switch (action) { 82 | case Input_Press: { 83 | _state.button_frame_states[button] = 0b00000001; 84 | _state.button_current_states[button] = 1; 85 | _state.mouse_recordedx = _state.mouse_x; 86 | _state.mouse_recordedy = _state.mouse_y; 87 | } break; 88 | case Input_Release: { 89 | _state.button_frame_states[button] = 0b00000010; 90 | _state.button_current_states[button] = 0; 91 | _state.mouse_recordedx = _state.mouse_x; 92 | _state.mouse_recordedy = _state.mouse_y; 93 | } break; 94 | } 95 | } 96 | 97 | void __OS_InputCursorPosCallback(f32 xpos, f32 ypos) { 98 | _state.mouse_x = xpos; 99 | _state.mouse_y = ypos; 100 | } 101 | 102 | void __OS_InputScrollCallback(f32 xscroll, f32 yscroll) { 103 | _state.mouse_scrollx = xscroll; 104 | _state.mouse_scrolly = yscroll; 105 | _state.mouse_absscrollx += xscroll; 106 | _state.mouse_absscrolly += yscroll; 107 | } 108 | 109 | void __OS_InputReset(void) { 110 | memset(_state.key_frame_states, 0, 350 * sizeof(u8)); 111 | memset(_state.button_frame_states, 0, 8 * sizeof(u8)); 112 | _state.mouse_scrollx = 0; 113 | _state.mouse_scrolly = 0; 114 | } 115 | 116 | b32 OS_InputKey(u8 key) { return _state.key_current_states[key]; } 117 | b32 OS_InputKeyPressed(u8 key) { return (_state.key_frame_states[key] == 0b00000001); } 118 | b32 OS_InputKeyReleased(u8 key) { return (_state.key_frame_states[key] == 0b00000010); } 119 | b32 OS_InputKeyHeld(u8 key) { return (_state.key_frame_states[key] == 0b00000100); } 120 | b32 OS_InputButton(u8 button) { return _state.button_current_states[button]; } 121 | b32 OS_InputButtonPressed(u8 button) 122 | { return (_state.button_frame_states[button] == 0b00000001); } 123 | b32 OS_InputButtonReleased(u8 button) 124 | { return (_state.button_frame_states[button] == 0b00000010); } 125 | f32 OS_InputGetMouseX() { return _state.mouse_x; } 126 | f32 OS_InputGetMouseY() { return _state.mouse_y; } 127 | f32 OS_InputGetMouseScrollX() { return _state.mouse_scrollx; } 128 | f32 OS_InputGetMouseScrollY() { return _state.mouse_scrolly; } 129 | f32 OS_InputGetMouseAbsoluteScrollX() { return _state.mouse_absscrollx; } 130 | f32 OS_InputGetMouseAbsoluteScrollY() { return _state.mouse_absscrolly; } 131 | f32 OS_InputGetMouseDX() { return _state.mouse_x - _state.mouse_recordedx; } 132 | f32 OS_InputGetMouseDY() { return _state.mouse_y - _state.mouse_recordedy; } 133 | f32 OS_InputGetMouseRecordedX() { return _state.mouse_recordedx; } 134 | f32 OS_InputGetMouseRecordedY() { return _state.mouse_recordedy; } 135 | -------------------------------------------------------------------------------- /source/os/input.h: -------------------------------------------------------------------------------- 1 | /* date = July 15th 2022 5:07 pm */ 2 | 3 | #ifndef INPUT_H 4 | #define INPUT_H 5 | 6 | // Common KeyCodes 7 | #include "key_codes.h" 8 | 9 | #if defined(PLATFORM_WIN) 10 | # include "impl/win32_key_code_translate.h" 11 | #elif defined(PLATFORM_LINUX) 12 | # include "impl/x11_key_code_translate.h" 13 | #endif 14 | 15 | void __OS_InputKeyCallback(u8 key, i32 action); 16 | b8 __OS_InputKeyCallbackCheckRepeat(u8 key, i32 action); 17 | void __OS_InputButtonCallback(u8 button, i32 action); 18 | void __OS_InputCursorPosCallback(f32 xpos, f32 ypos); 19 | void __OS_InputScrollCallback(f32 xscroll, f32 yscroll); 20 | void __OS_InputReset(void); 21 | 22 | b32 OS_InputKey(u8 key); 23 | b32 OS_InputKeyPressed(u8 key); 24 | b32 OS_InputKeyReleased(u8 key); 25 | b32 OS_InputKeyHeld(u8 key); 26 | b32 OS_InputButton(u8 button); 27 | b32 OS_InputButtonPressed(u8 button); 28 | b32 OS_InputButtonReleased(u8 button); 29 | f32 OS_InputGetMouseX(); 30 | f32 OS_InputGetMouseY(); 31 | f32 OS_InputGetMouseScrollX(); 32 | f32 OS_InputGetMouseScrollY(); 33 | f32 OS_InputGetMouseAbsoluteScrollX(); 34 | f32 OS_InputGetMouseAbsoluteScrollY(); 35 | f32 OS_InputGetMouseDX(); 36 | f32 OS_InputGetMouseDY(); 37 | f32 OS_InputGetMouseRecordedX(); 38 | f32 OS_InputGetMouseRecordedY(); 39 | 40 | #endif //INPUT_H 41 | -------------------------------------------------------------------------------- /source/os/key_codes.h: -------------------------------------------------------------------------------- 1 | /* date = April 19th 2023 7:51 pm */ 2 | 3 | #ifndef KEY_CODES_H 4 | #define KEY_CODES_H 5 | 6 | #define Input_Press 1 7 | #define Input_Release 2 8 | #define Input_Repeat 3 9 | 10 | #define Input_MouseButton_Left 0 11 | #define Input_MouseButton_Middle 1 12 | #define Input_MouseButton_Right 2 13 | 14 | #define Input_Key_LeftArrow 37 15 | #define Input_Key_UpArrow 38 16 | #define Input_Key_RightArrow 39 17 | #define Input_Key_DownArrow 40 18 | 19 | #define Input_Key_Minus 189 20 | #define Input_Key_Equals 187 21 | #define Input_Key_Backspace 8 22 | 23 | #define Input_Key_Numpad0 45 24 | #define Input_Key_Numpad1 35 25 | #define Input_Key_Numpad2 40 26 | #define Input_Key_Numpad3 34 27 | #define Input_Key_Numpad4 37 28 | #define Input_Key_Numpad5 12 29 | #define Input_Key_Numpad6 39 30 | #define Input_Key_Numpad7 36 31 | #define Input_Key_Numpad8 38 32 | #define Input_Key_Numpad9 33 33 | #define Input_Key_NumpadPlus 107 34 | #define Input_Key_NumpadMinus 109 35 | #define Input_Key_NumpadStar 106 36 | #define Input_Key_NumpadSlash 111 37 | #define Input_Key_NumpadPeriod 46 38 | 39 | #define Input_Key_LeftShift 160 40 | #define Input_Key_RightShift 161 41 | #define Input_Key_LeftControl 162 42 | #define Input_Key_RightControl 163 43 | #define Input_Key_LeftAlt 164 44 | #define Input_Key_RightAlt 165 45 | #define Input_Key_CapsLock 20 46 | #define Input_Key_ScrollLock 145 47 | #define Input_Key_NumLock 144 48 | #define Input_Key_Grave 192 49 | #define Input_Key_Enter 13 50 | 51 | #define Input_Key_Period 190 52 | #define Input_Key_Comma 188 53 | #define Input_Key_ForwardSlash 191 54 | #define Input_Key_BackSlash 220 55 | #define Input_Key_Semicolon 186 56 | #define Input_Key_Apostrophe 222 57 | #define Input_Key_OpenBracket 219 58 | #define Input_Key_CloseBracket 221 59 | #define Input_Key_Escape 27 60 | #define Input_Key_Pause 19 61 | 62 | #define Input_Key_F1 112 63 | #define Input_Key_F2 113 64 | #define Input_Key_F3 114 65 | #define Input_Key_F4 115 66 | #define Input_Key_F5 116 67 | #define Input_Key_F6 117 68 | #define Input_Key_F7 118 69 | #define Input_Key_F8 119 70 | #define Input_Key_F9 120 71 | #define Input_Key_F10 121 72 | #define Input_Key_F11 122 73 | #define Input_Key_F12 123 74 | 75 | #define Input_Key_PageUp 33 76 | #define Input_Key_PageDown 34 77 | #define Input_Key_End 35 78 | #define Input_Key_Home 36 79 | #define Input_Key_Insert 45 80 | #define Input_Key_Delete 46 81 | 82 | #endif //KEY_CODES_H 83 | -------------------------------------------------------------------------------- /source/os/os.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | 3 | #include "os.h" 4 | 5 | #if defined(PLATFORM_WIN) 6 | #include "impl/win32_os.c" 7 | #elif defined(PLATFORM_LINUX) 8 | #include "impl/linux_os.c" 9 | #endif 10 | -------------------------------------------------------------------------------- /source/os/os.h: -------------------------------------------------------------------------------- 1 | /* date = March 31st 2022 1:23 pm */ 2 | 3 | #ifndef OS_H 4 | #define OS_H 5 | 6 | #include "base/mem.h" 7 | #include "base/str.h" 8 | #include "base/utils.h" 9 | 10 | //~ OS Init 11 | 12 | void OS_Init(void); 13 | 14 | //~ TLS 15 | 16 | void OS_ThreadContextSet(void* ctx); 17 | void* OS_ThreadContextGet(void); 18 | 19 | //~ Memory 20 | 21 | void* OS_MemoryReserve(u64 size); 22 | void OS_MemoryCommit(void* memory, u64 size); 23 | void OS_MemoryDecommit(void* memory, u64 size); 24 | void OS_MemoryRelease(void* memory, u64 size); 25 | 26 | //~ Files 27 | 28 | b32 OS_FileCreate(string filename); 29 | 30 | b32 OS_FileExists(string filename); 31 | b32 OS_FileRename(string filename, string new_name); 32 | string OS_FileRead(M_Arena* arena, string filename); 33 | b32 OS_FileCreateWrite(string filename, string data); 34 | b32 OS_FileCreateWrite_List(string filename, string_list data); 35 | b32 OS_FileWrite(string filename, string data); 36 | b32 OS_FileWrite_List(string filename, string_list data); 37 | void OS_FileOpen(string filename); 38 | 39 | b32 OS_FileDelete(string filename); 40 | 41 | b32 OS_FileCreateDir(string dirname); 42 | b32 OS_FileDeleteDir(string dirname); 43 | void OS_FileOpenDir(string dirname); 44 | 45 | //~ Utility Paths 46 | 47 | typedef u32 OS_SystemPath; 48 | enum { 49 | SystemPath_CurrentDir, 50 | SystemPath_Binary, 51 | SystemPath_UserData, 52 | SystemPath_TempData, 53 | }; 54 | 55 | string OS_Filepath(M_Arena* arena, OS_SystemPath path); 56 | 57 | //~ File Properties 58 | 59 | typedef u32 OS_DataAccessFlags; 60 | enum { 61 | DataAccess_Read = 0x1, 62 | DataAccess_Write = 0x2, 63 | DataAccess_Exec = 0x4, 64 | }; 65 | 66 | typedef u32 OS_FilePropertyFlags; 67 | enum { 68 | FileProperty_IsFolder = 0x1, 69 | }; 70 | 71 | typedef struct OS_FileProperties { 72 | u64 size; 73 | U_DenseTime create_time; 74 | U_DenseTime modify_time; 75 | OS_FilePropertyFlags flags; 76 | OS_DataAccessFlags access; 77 | } OS_FileProperties; 78 | 79 | OS_FileProperties OS_FileGetProperties(string filename); 80 | 81 | //~ File Iterator 82 | 83 | // Just a big buffer. will be OS specific 84 | typedef struct OS_FileIterator { 85 | u8 v[640]; 86 | } OS_FileIterator; 87 | 88 | OS_FileIterator OS_FileIterInit(string path); 89 | OS_FileIterator OS_FileIterInitPattern(string path); 90 | b32 OS_FileIterNext(M_Arena* arena, OS_FileIterator* iter, string* name_out, OS_FileProperties* prop_out); 91 | void OS_FileIterEnd(OS_FileIterator* iter); 92 | 93 | //~ Time 94 | 95 | U_DateTime OS_TimeUniversalNow(void); 96 | U_DateTime OS_TimeLocalFromUniversal(U_DateTime* date_time); 97 | U_DateTime OS_TimeUniversalFromLocal(U_DateTime* date_time); 98 | 99 | u64 OS_TimeMicrosecondsNow(void); 100 | void OS_TimeSleepMilliseconds(u32 t); 101 | 102 | //~ Shared Libraries 103 | 104 | // Just a buffer. will be OS specific 105 | typedef struct OS_Library { 106 | u64 v[1]; 107 | } OS_Library; 108 | 109 | OS_Library OS_LibraryLoad(string path); 110 | void_func* OS_LibraryGetFunction(OS_Library lib, char* name); 111 | void OS_LibraryRelease(OS_Library lib); 112 | 113 | //~ Threading 114 | 115 | typedef u64 thread_func(void* context); 116 | 117 | typedef struct OS_Thread { 118 | u64 v[1]; 119 | } OS_Thread; 120 | 121 | OS_Thread OS_ThreadCreate(thread_func* start, void* context); 122 | void OS_ThreadWaitForJoin(OS_Thread* other); 123 | void OS_ThreadWaitForJoinAll(OS_Thread** threads, u32 count); 124 | void OS_ThreadWaitForJoinAny(OS_Thread** threads, u32 count); 125 | 126 | #endif //OS_H 127 | -------------------------------------------------------------------------------- /source/os/window.c: -------------------------------------------------------------------------------- 1 | #include "defines.h" 2 | #include "base/base.h" 3 | 4 | #include "window.h" 5 | 6 | #if defined(PLATFORM_WIN) 7 | #include "impl/win32_window.c" 8 | #elif defined(PLATFORM_LINUX) 9 | #include "impl/x11_window.c" 10 | #endif 11 | -------------------------------------------------------------------------------- /source/os/window.h: -------------------------------------------------------------------------------- 1 | /* date = July 7th 2022 6:01 pm */ 2 | 3 | #ifndef WINDOW_H 4 | #define WINDOW_H 5 | 6 | #include "base/mem.h" 7 | #include "base/str.h" 8 | 9 | typedef struct OS_Window OS_Window; 10 | typedef void ResizeCallback(OS_Window* window, i32 w, i32 h); 11 | typedef void KeyCallback(OS_Window* window, u8 key, i32 action); 12 | typedef void ButtonCallback(OS_Window* window, u8 button, i32 action); 13 | 14 | struct OS_Window { 15 | u32 width; 16 | u32 height; 17 | string title; 18 | ResizeCallback* resize_callback; 19 | KeyCallback* key_callback; 20 | ButtonCallback* button_callback; 21 | void* user_data; 22 | u64 v[8]; 23 | }; 24 | 25 | OS_Window* OS_WindowCreate(u32 width, u32 height, string title); 26 | void OS_WindowShow(OS_Window* window); 27 | b8 OS_WindowIsOpen(OS_Window* window); 28 | void OS_WindowSetOpen(b8 open); 29 | void OS_PollEvents(void); 30 | void OS_WindowClose(OS_Window* window); 31 | 32 | #endif //WINDOW_H 33 | -------------------------------------------------------------------------------- /third_party/include/ft2build.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * 3 | * ft2build.h 4 | * 5 | * FreeType 2 build and setup macros. 6 | * 7 | * Copyright (C) 1996-2023 by 8 | * David Turner, Robert Wilhelm, and Werner Lemberg. 9 | * 10 | * This file is part of the FreeType project, and may only be used, 11 | * modified, and distributed under the terms of the FreeType project 12 | * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 | * this file you indicate that you have read the license and 14 | * understand and accept it fully. 15 | * 16 | */ 17 | 18 | 19 | /************************************************************************** 20 | * 21 | * This is the 'entry point' for FreeType header file inclusions, to be 22 | * loaded before all other header files. 23 | * 24 | * A typical example is 25 | * 26 | * ``` 27 | * #include 28 | * #include 29 | * ``` 30 | * 31 | */ 32 | 33 | 34 | #ifndef FT2BUILD_H_ 35 | #define FT2BUILD_H_ 36 | 37 | #include 38 | 39 | #endif /* FT2BUILD_H_ */ 40 | 41 | 42 | /* END */ 43 | --------------------------------------------------------------------------------