1. cleaned up WindowProc, 2. implemented hotkey callbacks

This commit is contained in:
Dennis Eichhorn 2024-10-04 14:17:20 +02:00
parent 223edfd595
commit 3494641cac
14 changed files with 169 additions and 74 deletions

View File

@ -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;

18
gpuapi/AntiAliasing.h Normal file
View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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 <windows.h>
#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);
}
}
}
}

View File

@ -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__)

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -98,7 +98,7 @@ uint64 time_ms()
QueryPerformanceCounter(&counter);
return (counter.QuadPart * 1000) / frequency.QuadPart;
return (counter.QuadPart * 1000000) / frequency.QuadPart;
}
inline void

View File

@ -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);
}

View File

@ -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;

View File

@ -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));

View File

@ -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;