diff --git a/font/Font.h b/font/Font.h index efc168f..01cce1c 100644 --- a/font/Font.h +++ b/font/Font.h @@ -4,6 +4,18 @@ #include "../stdlib/Types.h" #include "../memory/BufferMemory.h" +enum TextAlignH { + TEXT_ALIGN_H_LEFT, + TEXT_ALIGN_H_CENTER, + TEXT_ALIGN_H_RIGHT, +}; + +enum TextAlignV { + TEXT_ALIGN_V_BOTTOM, + TEXT_ALIGN_V_CENTER, + TEXT_ALIGN_V_TOP, +}; + struct GlyphMetrics { f32 width; // Width of the glyph f32 height; // Height of the glyph @@ -29,6 +41,7 @@ struct Glyph { struct Font { uint32 glyph_count; + f32 size; // Default font size uint32 line_height; Glyph* glyphs; diff --git a/gpuapi/AntiAliasing.h b/gpuapi/AntiAliasing.h new file mode 100644 index 0000000..7ee749d --- /dev/null +++ b/gpuapi/AntiAliasing.h @@ -0,0 +1,18 @@ +/** + * Jingga + * + * @copyright Jingga + * @license OMS License 2.0 + * @version 1.0.0 + * @link https://jingga.app + */ +#ifndef TOS_GPUAPI_ANTI_ALIASING_H +#define TOS_GPUAPI_ANTI_ALIASING_H + +enum AntiAliasingType { + ANTI_ALIASING_TYPE_NONE, + ANTI_ALIASING_TYPE_MSAA, + ANTI_ALIASING_TYPE_SSAA, +}; + +#endif \ No newline at end of file diff --git a/gpuapi/opengl/OpenglUtils.h b/gpuapi/opengl/OpenglUtils.h index a81ea50..2d272cb 100644 --- a/gpuapi/opengl/OpenglUtils.h +++ b/gpuapi/opengl/OpenglUtils.h @@ -124,7 +124,7 @@ void load_texture_to_gpu(const Texture* texture, int32 mipmap_level = 0) { uint32 texture_data_type = get_texture_data_type(texture->texture_data_type); glTexImage2D( - texture_data_type, mipmap_level, GL_RGBA8, + texture_data_type, mipmap_level, GL_RGBA, texture->image.width, texture->image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->image.pixels @@ -483,7 +483,7 @@ uint32 gpuapi_upload_color_palette(const byte* palette, int32 count, int32 sampl glActiveTexture(GL_TEXTURE0 + sampler_id); glBindTexture(GL_TEXTURE_1D, texture_id); - glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA8, count, 0, GL_RGBA, GL_UNSIGNED_BYTE, palette); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, count, 0, GL_RGBA, GL_UNSIGNED_BYTE, palette); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); diff --git a/gpuapi/opengl/OpenglWin32.h b/gpuapi/opengl/OpenglWin32.h index 8c06580..b9a5dde 100644 --- a/gpuapi/opengl/OpenglWin32.h +++ b/gpuapi/opengl/OpenglWin32.h @@ -1303,6 +1303,9 @@ static type_glProgramParameteri* glProgramParameteri; #define WGL_ALPHA_BITS_ARB 0x201B #define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + typedef HGLRC WINAPI wgl_create_context_attribs_arb(HDC hDC, HGLRC hShareContext, const int *attribList); static wgl_create_context_attribs_arb* wglCreateContextAttribsARB; @@ -1321,7 +1324,7 @@ static wgl_swap_interval_ext* wglSwapIntervalEXT; typedef const char* WINAPI wgl_get_extensions_string_ext(void); static wgl_get_extensions_string_ext* wglGetExtensionsStringEXT; -void set_pixel_format(HDC hdc) +void set_pixel_format(HDC hdc, int32 multisampling = 0) { int32 suggested_pixel_format_idx = 0; uint32 extended_pick = 0; @@ -1334,6 +1337,8 @@ void set_pixel_format(HDC hdc) WGL_DOUBLE_BUFFER_ARB, GL_TRUE, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE, + WGL_SAMPLE_BUFFERS_ARB, (int32) (multisampling > 0), + WGL_SAMPLES_ARB, multisampling, // 4x MSAA 0, }; @@ -1414,7 +1419,7 @@ bool gl_extensions_load() pos = end; } - wglMakeCurrent(0, 0); + wglMakeCurrent(NULL, NULL); wglDeleteContext(openGLRC); ReleaseDC(window, hdc); @@ -1504,24 +1509,32 @@ void opengl_init_gl() glProgramParameteri = (type_glProgramParameteri *) wglGetProcAddress("glProgramParameteri"); } -void opengl_init(Window* window) +void opengl_destroy(Window* window) +{ + wglMakeCurrent(NULL, NULL); + wglDeleteContext(window->openGLRC); + ReleaseDC(window->hwnd, window->hdc); +} + +void opengl_init(Window* window, int32 multisample = 0) { gl_extensions_load(); opengl_init_wgl(); - set_pixel_format(window->hdc); + window->hdc = GetDC(window->hwnd); + set_pixel_format(window->hdc, multisample); - HGLRC openGLRC = 0; + window->openGLRC = 0; if (wglCreateContextAttribsARB) { - openGLRC = wglCreateContextAttribsARB(window->hdc, 0, win32_opengl_attribs); + window->openGLRC = wglCreateContextAttribsARB(window->hdc, 0, win32_opengl_attribs); } - if (!openGLRC) { - openGLRC = wglCreateContext(window->hdc); + if (!window->openGLRC) { + window->openGLRC = wglCreateContext(window->hdc); } - if(!wglMakeCurrent(window->hdc, openGLRC)) { + if(!wglMakeCurrent(window->hdc, window->openGLRC)) { return; } diff --git a/input/Input.h b/input/Input.h index f41af8d..7122ee6 100644 --- a/input/Input.h +++ b/input/Input.h @@ -9,6 +9,10 @@ #ifndef TOS_INPUT_H #define TOS_INPUT_H +#include "../stdlib/Types.h" +#include "../utils/BitUtils.h" +#include "ControllerInput.h" + // How many concurrent mouse/secondary input device presses to we recognize #define MAX_MOUSE_PRESSES 3 @@ -24,6 +28,7 @@ // How often can a key be asigned to a different hotkey #define MAX_KEY_TO_HOTKEY 5 +#define MEX_KEY_LENGTH ((MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS + MAX_CONTROLLER_KEYS) * MAX_KEY_TO_HOTKEY) // How many buttons together are allowed to form a hotkey #define MAX_HOTKEY_COMBINATION 3 @@ -42,29 +47,28 @@ #define INPUT_LONG_PRESS_DURATION 250 -#include "../stdlib/Types.h" -#include "../utils/BitUtils.h" -#include "ControllerInput.h" - #ifdef _WIN32 #include #endif +typedef void (*InputCallback)(void* data); + // @todo I'm not sure if I like the general input handling // Having separate keyboard_down and mouse_down etc. is a little bit weird in the functions below struct InputMapping { // A key/button can be bound to up to 5 different hotkeys // This is used to check if a key/button has a hotkey association - // @todo why is this using 2d array while hotkeys uses 1d array? make both 1d arrays - uint8 keys[MAX_MOUSE_KEYS + MAX_KEYBOARD_KEYS + MAX_CONTROLLER_KEYS][MAX_KEY_TO_HOTKEY]; + uint8 keys[MEX_KEY_LENGTH]; // A hotkey can be bound to a combination of up to 3 key/button presses uint8 hotkey_count; // negative hotkeys mean any of them needs to be matched, positive hotkeys means all of them need to be matched // mixing positive and negative keys for one hotkey is not possible + // index = hotkey, value = key id int16* hotkeys; + InputCallback* callbacks; }; enum KeyState { @@ -77,7 +81,7 @@ struct InputKey { // Includes flag for mouse, keyboard, controller uint16 key_id; uint16 key_state; - int16 value; // e.g. stick/trigger keys + int16 value; // e.g. stick/trigger keys have additional values uint64 time; // when was this action performed (useful to decide if key state is held vs pressed) }; @@ -125,6 +129,8 @@ struct Input { bool state_change_button; bool state_change_mouse; + // Do we want to capture mouse events = true, + // or do we want to poll the position whenever needed = false bool mouse_movement; InputState state; @@ -132,10 +138,48 @@ struct Input { uint32 deadzone = 10; + // This data is passed to the hotkey callback + void* callback_data; + InputMapping input_mapping1; InputMapping input_mapping2; }; +inline +void input_init(Input* input, uint8 size, void* callback_data, BufferMemory* buf) +{ + // Init input + input->callback_data = callback_data; + + // Init mapping1 + input->input_mapping1.hotkey_count = size; + + input->input_mapping1.hotkeys = (int16 *) buffer_get_memory( + buf, + input->input_mapping1.hotkey_count * MAX_HOTKEY_COMBINATION * sizeof(int16) + ); + + input->input_mapping1.callbacks = (InputCallback *) buffer_get_memory( + buf, + input->input_mapping1.hotkey_count * sizeof(InputCallback), + 0, true + ); + + // Init mapping2 + input->input_mapping2.hotkey_count = size; + + input->input_mapping2.hotkeys = (int16 *) buffer_get_memory( + buf, + input->input_mapping2.hotkey_count * MAX_HOTKEY_COMBINATION * sizeof(int16) + ); + + input->input_mapping2.callbacks = (InputCallback *) buffer_get_memory( + buf, + input->input_mapping2.hotkey_count * sizeof(InputCallback), + 0, true + ); +} + inline void input_clean_state(InputState* state) { @@ -254,6 +298,11 @@ bool inputs_are_down( && (key4 == 0 || input_is_down(state, key4)); } +void input_add_callback(InputMapping* mapping, uint8 hotkey, InputCallback callback) +{ + mapping->callbacks[hotkey] = callback; +} + // We are binding hotkeys bi-directional void input_add_hotkey( @@ -312,18 +361,18 @@ input_add_hotkey( break; } - if (key0 != 0 && mapping->keys[key0 + key0_offset - 1][i] == 0) { - mapping->keys[key0 + key0_offset - 1][i] = hotkey; + if (key0 != 0 && mapping->keys[(key0 + key0_offset - 1) * MAX_KEY_TO_HOTKEY + i] == 0) { + mapping->keys[(key0 + key0_offset - 1) * MAX_KEY_TO_HOTKEY + i] = hotkey; key0 = 0; // prevent adding same key again } - if (key1 != 0 && mapping->keys[key1 + key1_offset - 1][i] == 0) { - mapping->keys[key1 + key1_offset - 1][i] = hotkey; + if (key1 != 0 && mapping->keys[(key1 + key1_offset - 1) * MAX_KEY_TO_HOTKEY + i] == 0) { + mapping->keys[(key1 + key1_offset - 1) * MAX_KEY_TO_HOTKEY + i] = hotkey; key1 = 0; // prevent adding same key again } - if (key2 != 0 && mapping->keys[key2 + key2_offset - 1][i] == 0) { - mapping->keys[key2 + key2_offset - 1][i] = hotkey; + if (key2 != 0 && mapping->keys[(key2 + key2_offset - 1) * MAX_KEY_TO_HOTKEY + i] == 0) { + mapping->keys[(key2 + key2_offset - 1) * MAX_KEY_TO_HOTKEY + i] = hotkey; key2 = 0; // prevent adding same key again } } @@ -512,12 +561,12 @@ input_hotkey_state(Input* input) continue; } - if (mapping->keys[internal_key_id - 1][0] == 0) { + if (mapping->keys[(internal_key_id - 1) * MAX_KEY_TO_HOTKEY] == 0) { // no possible hotkey associated with this key continue; } - const uint8* hotkeys_for_key = mapping->keys[internal_key_id - 1]; + const uint8* hotkeys_for_key = mapping->keys + (internal_key_id - 1) * MAX_KEY_TO_HOTKEY; // Check every possible hotkey // Since multiple input devices have their own button/key indices whe have to do this weird range handling @@ -533,6 +582,11 @@ input_hotkey_state(Input* input) if (is_pressed && !hotkey_is_active(&input->state, hotkeys_for_key[possible_hotkey_idx])) { input->state.state_hotkeys[active_hotkeys] = hotkeys_for_key[possible_hotkey_idx]; ++active_hotkeys; + + // Run callback if defined + if (input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]] != 0) { + input->input_mapping1.callbacks[hotkeys_for_key[possible_hotkey_idx]](input->callback_data); + } } } } diff --git a/log/DebugMemory.h b/log/DebugMemory.h index 99bfdfb..ada3bbc 100644 --- a/log/DebugMemory.h +++ b/log/DebugMemory.h @@ -48,7 +48,7 @@ struct DebugMemoryContainer { DebugMemory* memory_stats; }; -#if DEBUG +#if DEBUG || INTERNAL #define DEBUG_MEMORY_INIT(start, size) debug_memory_init((start), (size)) #define DEBUG_MEMORY_READ(start, size) debug_memory_read((start), (size), __func__) #define DEBUG_MEMORY_WRITE(start, size) debug_memory_write((start), (size), __func__) diff --git a/log/TimingStat.h b/log/TimingStat.h index 3b9284a..681a854 100644 --- a/log/TimingStat.h +++ b/log/TimingStat.h @@ -31,7 +31,7 @@ struct TimingStat { // Sometimes we want to only do logging in debug mode. // In such cases use the following macro. -#if DEBUG +#if DEBUG || INTERNAL #define UPDATE_TIMING_STAT(stat) update_timing_stat(stat, __func__) #else #define UPDATE_TIMING_STAT(stat) ((void) 0) diff --git a/memory/ChunkMemory.h b/memory/ChunkMemory.h index 85129bf..76c5640 100644 --- a/memory/ChunkMemory.h +++ b/memory/ChunkMemory.h @@ -37,7 +37,7 @@ void chunk_alloc(ChunkMemory* buf, uint64 count, uint64 chunk_size, int32 alignm : (byte *) playform_alloc_aligned(count * chunk_size + sizeof(buf->free) * CEIL_DIV(count, 64), alignment); buf->count = count; - buf->size = chunk_size * count; + buf->size = chunk_size + sizeof(buf->free) * CEIL_DIV(count, 64); buf->chunk_size = chunk_size; buf->last_pos = -1; buf->alignment = alignment; diff --git a/models/settings/Settings.h b/models/settings/Settings.h index d274a42..21b3f93 100644 --- a/models/settings/Settings.h +++ b/models/settings/Settings.h @@ -165,6 +165,7 @@ struct CSettings { byte gpu_motion_blur = SETTING_TYPE_DISABLED; byte gpu_blur = SETTING_TYPE_DISABLED; byte gpu_anti_aliasing = SETTING_TYPE_DISABLED; + byte gpu_anti_aliasing_detail = 0; byte gpu_sharpening = SETTING_TYPE_DISABLED; byte gpu_ambient_occlusion = SETTING_TYPE_DISABLED; diff --git a/platform/win32/UtilsWin32.h b/platform/win32/UtilsWin32.h index 552a181..c4e51cc 100644 --- a/platform/win32/UtilsWin32.h +++ b/platform/win32/UtilsWin32.h @@ -98,7 +98,7 @@ uint64 time_ms() QueryPerformanceCounter(&counter); - return (counter.QuadPart * 1000) / frequency.QuadPart; + return (counter.QuadPart * 1000000) / frequency.QuadPart; } inline void diff --git a/platform/win32/UtilsWindows.h b/platform/win32/UtilsWindows.h index 887e93b..178d42a 100644 --- a/platform/win32/UtilsWindows.h +++ b/platform/win32/UtilsWindows.h @@ -15,18 +15,19 @@ #include "../../utils/TestUtils.h" inline -void window_inactive(Window* w) +void window_remove_style(Window* w) +{ + LONG_PTR style = GetWindowLongPtrA(w->hwnd, GWL_STYLE); + style &= ~WS_OVERLAPPEDWINDOW; + SetWindowLongPtr(w->hwnd, GWL_STYLE, style); +} + +inline +void window_add_style(Window* w) { LONG_PTR style = GetWindowLongPtrA(w->hwnd, GWL_STYLE); style |= WS_OVERLAPPEDWINDOW; SetWindowLongPtr(w->hwnd, GWL_STYLE, style); - - ClipCursor(NULL); - - // WARNING: Apparently this has an internal reference count, effecting if true/false actually take effect! - ShowCursor(true); - - w->mouse_captured = false; } inline @@ -37,51 +38,35 @@ void monitor_resolution(const Window* __restrict w, v2_int32* __restrict resolut } inline -void monitor_resolution(Window* __restrict w) +void monitor_resolution(Window* w) { w->width = (uint16) GetDeviceCaps(w->hdc, HORZRES); w->height = (uint16) GetDeviceCaps(w->hdc, VERTRES); } inline -void window_active(Window* __restrict w) +void window_resolution(Window* w) { - LONG_PTR style = GetWindowLongPtrA(w->hwnd, GWL_STYLE); - style &= ~WS_OVERLAPPEDWINDOW; - SetWindowLongPtr(w->hwnd, GWL_STYLE, style); - - SetWindowPos( - w->hwnd, HWND_TOP, - w->x, w->y, - w->width, w->height, - SWP_NOACTIVATE | SWP_NOZORDER - ); - RECT rect; - GetWindowRect(w->hwnd, &rect); - ClipCursor(&rect); + GetClientRect(w->hwnd, &rect); - // WARNING: Apparently this has an internal reference count, effecting if true/false actually take effect! - ShowCursor(false); - - w->mouse_captured = true; + w->width = (uint16) (rect.right - rect.left); + w->height = (uint16) (rect.bottom - rect.top); } inline -void window_fullscreen(Window* __restrict w) +void window_fullscreen(Window* w) { monitor_resolution(w); w->x = 0; w->y = 0; - LONG style = GetWindowLong(w->hwnd, GWL_STYLE); - SetWindowLongPtr(w->hwnd, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW); - - SetWindowPos(w->hwnd, HWND_TOP, 0, 0, w->width, w->height, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); + window_remove_style(w); + SetWindowPos(w->hwnd, HWND_TOP, 0, 0, w->width, w->height, SWP_NOACTIVATE | SWP_NOZORDER); } inline -void window_restore(Window* __restrict w) +void window_restore(Window* w) { window_restore_state(w); @@ -141,20 +126,20 @@ void window_create(Window* __restrict window, void* proc) NULL, NULL, hinstance, window ); - window->hdc = GetDC(window->hwnd); - ASSERT_SIMPLE(window->hwnd); } -void window_open(const Window* __restrict window) +void window_open(Window* window) { ShowWindow(window->hwnd, SW_SHOW); SetForegroundWindow(window->hwnd); SetFocus(window->hwnd); UpdateWindow(window->hwnd); + + window->state_changes |= WINDOW_STATE_CHANGE_FOCUS; } -void window_close(Window* __restrict window) +void window_close(Window* window) { CloseWindow(window->hwnd); } diff --git a/platform/win32/Window.h b/platform/win32/Window.h index 932a39f..24fdb20 100644 --- a/platform/win32/Window.h +++ b/platform/win32/Window.h @@ -21,6 +21,11 @@ struct WindowState { uint64 style; }; +#define WINDOW_STATE_CHANGE_SIZE 1 +#define WINDOW_STATE_CHANGE_POS 2 +#define WINDOW_STATE_CHANGE_FOCUS 4 +#define WINDOW_STATE_CHANGE_FULLSCREEN 8 + struct Window { uint16 width; uint16 height; @@ -28,11 +33,17 @@ struct Window { int32 x; int32 y; + // 1. position + // 2. focus + // 3. size + // 4. fullscreen + byte state_changes; + bool is_focused; bool is_fullscreen; - bool mouse_captured; HWND hwnd; HDC hdc; + HGLRC openGLRC; char name[32]; WindowState state_old; diff --git a/platform/win32/input/RawInput.h b/platform/win32/input/RawInput.h index 5549733..1ffb6c8 100644 --- a/platform/win32/input/RawInput.h +++ b/platform/win32/input/RawInput.h @@ -32,7 +32,7 @@ // Even if it is nowhere documented (at least not to our knowledge) the GetRawInputDeviceInfoA, GetRawInputBuffer functions requried // aligned memory. So far we only figured out that 4 bytes works, maybe this needs to be 8 in the future?! -int input_init(HWND hwnd, Input* __restrict states, RingMemory* ring) +int input_raw_init(HWND hwnd, Input* __restrict states, RingMemory* ring) { uint32 device_count; GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)); diff --git a/stdlib/simd/SIMD_F32.h b/stdlib/simd/SIMD_F32.h index 6bbaa08..bb4b3d0 100644 --- a/stdlib/simd/SIMD_F32.h +++ b/stdlib/simd/SIMD_F32.h @@ -638,7 +638,7 @@ inline f32_16 &operator|=(f32_16 &a, f32_16 b) inline f32_4 abs(f32_4 a) { - unsigned int unsigned_mask = (unsigned int) (1 << 31); + uint32 unsigned_mask = (uint32) (1U << 31); __m128 mask = _mm_set1_ps(*(f32 *) &unsigned_mask); f32_4 simd; @@ -649,7 +649,7 @@ inline f32_4 abs(f32_4 a) inline f32_8 abs(f32_8 a) { - unsigned int unsigned_mask = (unsigned int) (1 << 31); + uint32 unsigned_mask = (uint32) (1U << 31); __m256 mask = _mm256_set1_ps(*(f32 *) &unsigned_mask); f32_8 simd; @@ -716,7 +716,7 @@ inline f32_16 simd_max(f32_16 a, f32_16 b) inline f32_4 sign(f32_4 a) { - unsigned int umask = (unsigned int) (1 << 31); + uint32 umask = (uint32) (1U << 31); __m128 mask = _mm_set1_ps(*(f32 *) &umask); f32_4 signBit; @@ -732,7 +732,7 @@ inline f32_4 sign(f32_4 a) inline f32_8 sign(f32_8 a) { - unsigned int umask = (unsigned int) (1 << 31); + uint32 umask = (uint32) (1U << 31); __m256 mask = _mm256_set1_ps(*(f32 *) &umask); f32_8 signBit; @@ -748,7 +748,7 @@ inline f32_8 sign(f32_8 a) inline f32_16 sign(f32_16 a) { - unsigned int umask = (unsigned int) (1 << 31); + uint32 umask = (uint32) (1U << 31); __m512 mask = _mm512_set1_ps(*(f32 *) &umask); f32_16 signBit;