summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-06-07 09:51:24 -0400
committerAndrew Opalach <andrew@akon.city> 2025-06-07 09:51:24 -0400
commit658e476c3d43718a2c9eb2884f16ac37cc3f1da2 (patch)
treed8851ea63b0cd666db050eb093d299d4a469f89f
parenta2e04b98512e9db93d5457ecc52ac385b9a9e0aa (diff)
downloadstela-658e476c3d43718a2c9eb2884f16ac37cc3f1da2.tar.gz
stela-658e476c3d43718a2c9eb2884f16ac37cc3f1da2.tar.bz2
stela-658e476c3d43718a2c9eb2884f16ac37cc3f1da2.zip
Window events refactor, slight GL cleanup
- Support orientation and touch events from GLFM. Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--meson.build10
-rw-r--r--src/egl_common.c10
-rw-r--r--src/gl_common.h28
-rw-r--r--src/window.c194
-rw-r--r--src/window.h57
-rw-r--r--src/window_glfm.c70
-rw-r--r--src/window_glfm.h1
-rw-r--r--src/window_glfw.c101
-rw-r--r--src/window_kms.c1
-rw-r--r--src/window_wayland.c47
-rw-r--r--src/window_win32.c40
-rw-r--r--src/window_win32.h1
-rw-r--r--src/window_x11.c7
-rw-r--r--subprojects/libalabaster.wrap2
-rw-r--r--subprojects/libnaunet.wrap2
15 files changed, 340 insertions, 231 deletions
diff --git a/meson.build b/meson.build
index 95e7991..dbe46b6 100644
--- a/meson.build
+++ b/meson.build
@@ -74,18 +74,22 @@ elif get_option('api') in ['gl', 'gles']
egl = dependency('egl')
stela_deps += [egl]
stela_src += ['src/egl_common.c']
- elif get_option('window') == 'win32'
- stela_deps += [compiler.find_library('opengl32')]
endif
if use_glad
glad_opts = use_gles ? 'use_gles=true' : 'use_gles=false'
stela_deps += [subproject('glad', default_options: glad_opts).get_variable('glad')]
stela_args += ['-DSTELA_USE_GLAD']
- elif not is_android and not is_windows
+ elif is_windows
+ stela_deps += [compiler.find_library('opengl32')]
+ elif not is_android
stela_deps += [dependency('gl')]
endif
if use_gles
stela_args += ['-DSTELA_USE_GLES']
+ else
+ if compiler.has_header('GL/glext.h')
+ stela_args += ['-DSTELA_HAS_GLEXT']
+ endif
endif
stela_src += ['src/gl_common.c']
stela_args += ['-DSTELA_API_OPENGL']
diff --git a/src/egl_common.c b/src/egl_common.c
index ad2bea3..7ed6a62 100644
--- a/src/egl_common.c
+++ b/src/egl_common.c
@@ -2,6 +2,7 @@
#include <al/log.h>
#include <al/macros.h>
+#ifdef STELA_API_OPENGL
#include "egl_common.h"
#define STELA_GL_API EGL_OPENGL_API
@@ -16,6 +17,7 @@
#include "gl_versions.h"
PASTE_GL_VERSIONS()
+#endif
bool stl_maybe_load_egl(void)
{
@@ -185,7 +187,6 @@ bool stl_egl_make_current(struct stl_egl *egl)
void stl_egl_release_current(struct stl_egl *egl)
{
- al_assert(egl->context == egl->current);
// https://gitlab.freedesktop.org/mesa/mesa/-/issues/6547
// libplacebo calls release_current() after swapping buffers. That locks in the
// current backbuffer size. So, if all that happens for the next frame is:
@@ -196,9 +197,12 @@ void stl_egl_release_current(struct stl_egl *egl)
// 5. swap buffers
// The frame that is presented will still have the dimensions of the previous backbuffer.
// We only support 1 context at a time, so this shouldn't be an issue.
+ al_assert(egl->context == egl->current);
#if 0
- eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- egl->current = EGL_NO_CONTEXT;
+ if (egl->current != EGL_NO_CONTEXT) {
+ eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ egl->current = EGL_NO_CONTEXT;
+ }
#endif
}
diff --git a/src/gl_common.h b/src/gl_common.h
index ae49215..9173aa4 100644
--- a/src/gl_common.h
+++ b/src/gl_common.h
@@ -4,9 +4,6 @@
#include <nnwt/windows.h>
#endif
-#ifdef STELA_WINDOW_GLFM
-#include <glfm.h>
-#else
#ifdef STELA_USE_GLAD
#ifdef STELA_USE_GLES
#include <glad/gles2.h>
@@ -16,29 +13,24 @@
#else
#ifdef STELA_USE_GLES
#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2platform.h>
+/*
+#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
+#include <GLES3/gl32.h>
+#include <GLES3/gl3ext.h>
+#include <GLES3/gl3platform.h>
+*/
#else
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
-#ifndef NAUNET_ON_WINDOWS
+#ifdef STELA_HAS_GLEXT
#include <GL/glext.h>
#include <GL/glcorearb.h>
#endif
#endif
#endif
-#endif
-
-#ifdef NAUNET_ON_WINDOWS
-// https://registry.khronos.org/OpenGL/api/GL/wgl.h
-#define WGL_CONTEXT_FLAGS_ARB 0x2094
-#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
-#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
-#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
-#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
-#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
-#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
-#endif
bool stl_gl_check_error();
bool stl_gl_loader_load(void (*(*get_proc_address)(const char *))(void));
diff --git a/src/window.c b/src/window.c
index 6f57c80..08dc625 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3,10 +3,55 @@
#include "window.h"
+static bool nop_pointer_pos_callback(void *userdata, f64 x, f64 y)
+{
+ (void)userdata;
+ (void)x;
+ (void)y;
+ return false;
+}
+
+static bool nop_touch_callback(void *userdata, s32 index, u8 phase, f64 x, f64 y)
+{
+ (void)userdata;
+ (void)index;
+ (void)phase;
+ (void)x;
+ (void)y;
+ return false;
+}
+
+static bool nop_scroll_callback(void *userdata, f64 y)
+{
+ (void)userdata;
+ (void)y;
+ return false;
+}
+
+static bool nop_mouse_button_callback(void *userdata, u8 state, u8 button)
+{
+ (void)userdata;
+ (void)state;
+ (void)button;
+ return false;
+}
+
+static bool nop_key_callback(void *userdata, u8 state, u16 button)
+{
+ (void)userdata;
+ (void)state;
+ (void)button;
+ return false;
+}
+
void stl_window_init(struct stl_window *window)
{
+ window->pointer_pos_callback = nop_pointer_pos_callback;
+ window->touch_callback = nop_touch_callback;
+ window->scroll_callback = nop_scroll_callback;
+ window->mouse_button_callback = nop_mouse_button_callback;
+ window->key_callback = nop_key_callback;
#ifdef STELA_EVENT_BUFFER
- window->data = al_malloc(STELA_EVENTS_SIZE);
al_ring_buffer_init(&window->events, window->data, STELA_EVENTS_SIZE);
#endif
#ifdef STELA_PAUSE
@@ -21,9 +66,16 @@ void stl_window_created(struct stl_window *window, u32 width, u32 height, u32 fl
window->flags = flags;
}
+void stl_window_send_render_event(struct stl_window *window)
+{
+ if (window->render_callback) {
+ window->render_callback(window->userdata);
+ }
+}
+
#ifdef STELA_EVENT_BUFFER
#define GET_EVENT_CHUNK(op) \
- size_t size; \
+ ptrdiff_t size; \
u8 *ptr = al_ring_buffer_write_chunk(&window->events, &size); \
if (size < STELA_EVENT_SIZE) { \
log_warn("Buffer full, discarding event."); \
@@ -35,6 +87,22 @@ void stl_window_created(struct stl_window *window, u32 width, u32 height, u32 fl
#define APPEND_EVENT_CHUNK() \
al_ring_buffer_append(&window->events, ptr, STELA_EVENT_SIZE)
+void stl_window_send_resize_event(struct stl_window *window, u32 width, u32 height)
+{
+ al_assert(width == window->width && height == window->height);
+#ifdef STELA_EVENT_BUFFER
+ window->pending_resize = true;
+#else
+ window->resize_internal(window, width, height);
+ if (window->resize_callback) {
+ window->resize_callback(window->userdata, width, height);
+ }
+#ifdef STELA_PAUSE
+ window->pending_refresh = true;
+#endif
+#endif
+}
+
void stl_window_send_pointer_pos_event(struct stl_window *window, f64 x, f64 y)
{
#ifdef STELA_EVENT_BUFFER
@@ -43,13 +111,27 @@ void stl_window_send_pointer_pos_event(struct stl_window *window, f64 x, f64 y)
((f64 *)(&ptr[9]))[0] = y;
APPEND_EVENT_CHUNK();
#else
- if (window->pointer_pos_callback) {
- if (window->pointer_pos_callback(window->userdata, x, y)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->pointer_pos_callback(window->userdata, x, y);
+#endif
+}
+
+void stl_window_send_touch_event(struct stl_window *window, s32 index, u8 phase, f64 x, f64 y)
+{
+#ifdef STELA_EVENT_BUFFER
+ GET_EVENT_CHUNK(STELA_EVENT_TOUCH);
+ ((s32 *)(&ptr[1]))[0] = index;
+ ptr[5] = phase;
+ ((f64 *)(&ptr[6]))[0] = x;
+ ((f64 *)(&ptr[14]))[0] = y;
+ APPEND_EVENT_CHUNK();
+#else
+#ifdef STELA_PAUSE
+ window->pending_refresh |=
+#endif
+ window->touch_callback(window->userdata, index, phase, x, y);
#endif
}
@@ -60,13 +142,10 @@ void stl_window_send_scroll_event(struct stl_window *window, f64 y)
((f64 *)(&ptr[1]))[0] = y;
APPEND_EVENT_CHUNK();
#else
- if (window->scroll_callback) {
- if (window->scroll_callback(window->userdata, y)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->scroll_callback(window->userdata, y);
#endif
}
@@ -78,13 +157,10 @@ void stl_window_send_mouse_button_event(struct stl_window *window, u8 state, u8
ptr[2] = button;
APPEND_EVENT_CHUNK();
#else
- if (window->mouse_button_callback) {
- if (window->mouse_button_callback(window->userdata, state, button)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->mouse_button_callback(window->userdata, state, button);
#endif
}
@@ -96,52 +172,20 @@ void stl_window_send_key_event(struct stl_window *window, u8 state, u16 button)
((u16 *)(&ptr[2]))[0] = button;
APPEND_EVENT_CHUNK();
#else
- if (window->key_callback) {
- if (window->key_callback(window->userdata, state, button)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->key_callback(window->userdata, state, button);
#endif
}
-void stl_window_send_resize_event(struct stl_window *window, u32 width, u32 height)
+void stl_window_send_key_immediate_event(struct stl_window *window, u8 state, u16 button)
{
-#ifdef STELA_EVENT_BUFFER
- (void)width;
- (void)height;
- window->pending_resize = true;
-#else
- window->resize_internal(window, width, height);
- if (window->resize_callback) {
- window->resize_callback(window->userdata, width, height);
+ if (window->key_immediate_callback) {
+ window->key_immediate_callback(window->userdata, state, button);
}
-#ifdef STELA_PAUSE
- window->pending_refresh = true;
-#endif
-#endif
}
-void stl_window_send_render_event(struct stl_window *window)
-{
- if (window->render_callback) {
- window->render_callback(window->userdata);
- }
-}
-
-#ifdef STELA_POLL_INLINE
-void stl_window_send_refresh_event(struct stl_window *window)
-{
- if (window->refresh_callback) {
- window->refresh_callback(window->userdata);
- }
-#ifdef STELA_PAUSE
- window->pending_refresh = true;
-#endif
-}
-#endif
-
void stl_window_send_should_close_event(struct stl_window *window)
{
#ifdef STELA_EVENT_BUFFER
@@ -160,70 +204,56 @@ bool stl_window_read_events(struct stl_window *window)
u8 op = STELA_EVENT_NONE;
if (window->pending_resize) {
- u32 width = window->width;
- u32 height = window->height;
- window->resize_internal(window, width, height);
+ op = STELA_EVENT_RESIZE;
+ window->resize_internal(window, window->width, window->height);
if (window->resize_callback) {
- window->resize_callback(window->userdata, width, height);
+ window->resize_callback(window->userdata, window->width, window->height);
}
#ifdef STELA_PAUSE
window->pending_refresh = true;
#endif
window->pending_resize = false;
- op = STELA_EVENT_RESIZE;
}
- size_t size;
+ ptrdiff_t size;
u8 *ptr = al_ring_buffer_read_chunk(&window->events, &size);
u8 *bc = ptr;
- while ((size_t)(bc - ptr) < size) {
+ while (bc - ptr < size) {
op = *bc;
switch (op) {
case STELA_EVENT_POINTER_POS: {
f64 x = ((f64 *)(&bc[1]))[0];
f64 y = ((f64 *)(&bc[9]))[0];
- if (window->pointer_pos_callback) {
- if (window->pointer_pos_callback(window->userdata, x, y)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->pointer_pos_callback(window->userdata, x, y);
break;
}
case STELA_EVENT_SCROLL: {
f64 y = ((f64 *)(&bc[1]))[0];
- if (window->scroll_callback) {
- if (window->scroll_callback(window->userdata, y)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->scroll_callback(window->userdata, y);
break;
}
case STELA_EVENT_MOUSE_BUTTON: {
u8 state = bc[1];
u8 button = bc[2];
- if (window->mouse_button_callback) {
- if (window->mouse_button_callback(window->userdata, state, button)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->mouse_button_callback(window->userdata, state, button);
break;
}
case STELA_EVENT_KEY: {
u8 state = bc[1];
u16 button = ((u16 *)(&bc[2]))[0];
- if (window->key_callback) {
- if (window->key_callback(window->userdata, state, button)) {
#ifdef STELA_PAUSE
- window->pending_refresh = true;
+ window->pending_refresh |=
#endif
- }
- }
+ window->key_callback(window->userdata, state, button);
break;
}
case STELA_EVENT_SHOULD_CLOSE: {
@@ -237,7 +267,7 @@ bool stl_window_read_events(struct stl_window *window)
}
bc += STELA_EVENT_SIZE;
}
- al_assert((size_t)(bc - ptr) == size);
+ al_assert(bc - ptr == size);
al_ring_buffer_consume(&window->events, ptr, size);
return op != STELA_EVENT_NONE;
diff --git a/src/window.h b/src/window.h
index d22b13d..cd4e81f 100644
--- a/src/window.h
+++ b/src/window.h
@@ -33,11 +33,11 @@
#endif
#ifndef STELA_MIN_WIDTH
-#define STELA_MIN_WIDTH 16
+#define STELA_MIN_WIDTH 16u
#endif
#ifndef STELA_MIN_HEIGHT
-#define STELA_MIN_HEIGHT 16
+#define STELA_MIN_HEIGHT 16u
#endif
enum {
@@ -55,21 +55,17 @@ struct stl_monitor {
char name[STELA_MAX_MONITOR_NAME];
};
+#define STELA_EVENT_SIZE 24u
+#ifndef STELA_EVENTS_SIZE
+#define STELA_EVENTS_SIZE (STELA_EVENT_SIZE * 64u)
+#endif
+
struct stl_window {
u32 width;
u32 height;
u32 scale;
bool fullscreen;
u32 flags;
-#ifdef STELA_EVENT_BUFFER
- u8 *data;
- // Render thread events.
- struct al_ring_buffer events;
- bool pending_resize;
-#endif
-#ifdef STELA_PAUSE
- bool pending_refresh;
-#endif
// Methods.
bool (*create_window)(struct stl_window *, u32, u32, const char *, const char *, u32);
void (*resize_internal)(struct stl_window *, u32, u32);
@@ -108,24 +104,34 @@ struct stl_window {
// Callbacks.
void (*output_discovered_callback)(void *, struct stl_monitor *);
void (*render_callback)(void *);
- void (*refresh_callback)(void *);
+ void (*resize_callback)(void *, u32, u32);
bool (*pointer_pos_callback)(void *, f64, f64);
+ bool (*touch_callback)(void *, s32, u8, f64, f64);
bool (*scroll_callback)(void *, f64);
bool (*mouse_button_callback)(void *, u8, u8);
bool (*key_callback)(void *, u8, u16);
- // Always runs on the thread that's processing events.
+ // Always runs on the thread that received the key event.
void (*key_immediate_callback)(void *, u8, u16);
- void (*resize_callback)(void *, u32, u32);
void (*should_close_callback)(void *);
void *userdata;
+#ifdef STELA_PAUSE
+ bool pending_refresh;
+#endif
+#ifdef STELA_EVENT_BUFFER
+ bool pending_resize;
+ // Render thread events.
+ struct al_ring_buffer events;
+ u8 data[STELA_EVENTS_SIZE];
+#endif
};
enum {
- STELA_EVENT_POINTER_POS = 0,
+ STELA_EVENT_RESIZE = 0,
+ STELA_EVENT_POINTER_POS,
+ STELA_EVENT_TOUCH,
STELA_EVENT_SCROLL,
STELA_EVENT_MOUSE_BUTTON,
STELA_EVENT_KEY,
- STELA_EVENT_RESIZE,
STELA_EVENT_SHOULD_CLOSE,
STELA_EVENT_NONE = 255
};
@@ -141,10 +147,13 @@ enum {
STELA_MOUSE3 = 1 << 2
};
-#define STELA_EVENT_SIZE 32
-#ifndef STELA_EVENTS_SIZE
-#define STELA_EVENTS_SIZE (STELA_EVENT_SIZE * 128)
-#endif
+enum {
+ STELA_TOUCH_HOVER = 0,
+ STELA_TOUCH_BEGAN,
+ STELA_TOUCH_MOVED,
+ STELA_TOUCH_ENDED,
+ STELA_TOUCH_CANCELLED
+};
extern s32 stl_platform_main(u32 argc, str *argv);
@@ -157,14 +166,14 @@ s32 stl_swallow_main(u32 argc, str *argv, s32 (*main)(u32, str *, void *), void
void stl_global_close(void);
struct stl_window *stl_window_create(void);
+void stl_window_send_render_event(struct stl_window *window);
+void stl_window_send_resize_event(struct stl_window *window, u32 width, u32 height);
void stl_window_send_pointer_pos_event(struct stl_window *window, f64 x, f64 y);
+void stl_window_send_touch_event(struct stl_window *window, s32 index, u8 phase, f64 x, f64 y);
void stl_window_send_scroll_event(struct stl_window *window, f64 y);
void stl_window_send_mouse_button_event(struct stl_window *window, u8 state, u8 button);
void stl_window_send_key_event(struct stl_window *window, u8 state, u16 button);
-void stl_window_send_resize_event(struct stl_window *window, u32 width, u32 height);
-#ifdef STELA_POLL_INLINE
-void stl_window_send_refresh_event(struct stl_window *window);
-#endif
+void stl_window_send_key_immediate_event(struct stl_window *window, u8 state, u16 button);
void stl_window_send_should_close_event(struct stl_window *window);
#ifdef STELA_EVENT_BUFFER
bool stl_window_read_events(struct stl_window *window);
diff --git a/src/window_glfm.c b/src/window_glfm.c
index b230f48..39de449 100644
--- a/src/window_glfm.c
+++ b/src/window_glfm.c
@@ -36,46 +36,92 @@ void stl_global_close(void)
static void onSurfaceCreated(GLFMDisplay *display, s32 width, s32 height)
{
- GLFMRenderingAPI api = glfmGetRenderingAPI(display);
(void)width;
(void)height;
- log_info("Created GLES context of version %s.",
- api == GLFMRenderingAPIOpenGLES32 ? "3.2" :
- api == GLFMRenderingAPIOpenGLES31 ? "3.1" :
- api == GLFMRenderingAPIOpenGLES3 ? "3.0" : "2.0");
if (!global.did_main) {
stl_platform_main(0, NULL);
global.did_main = true;
}
+ GLFMRenderingAPI api = glfmGetRenderingAPI(display);
+ log_info("Created GLES context of version %s.",
+ api == GLFMRenderingAPIOpenGLES32 ? "3.2" :
+ api == GLFMRenderingAPIOpenGLES31 ? "3.1" :
+ api == GLFMRenderingAPIOpenGLES3 ? "3.0" : "2.0");
+}
+
+static void onDraw(GLFMDisplay *display)
+{
+ struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display);
+ stl_window_send_render_event(&glfm->w);
}
static void onSurfaceDestroyed(GLFMDisplay *display)
{
- (void)display;
+ struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display);
+ stl_window_send_should_close_event(&glfm->w);
}
-static void onDraw(GLFMDisplay *display)
+static void swap_dimensions_and_send_resize(struct stl_window_glfm *glfm)
+{
+ SWAP(glfm->w.width, glfm->w.height);
+ stl_window_send_resize_event(&glfm->w, glfm->w.width, glfm->w.height);
+}
+
+static void onOrientationChanged(GLFMDisplay *display, GLFMInterfaceOrientation orientation)
{
struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display);
- if (glfm->w.render_callback) {
- glfm->w.render_callback(glfm->w.userdata);
+ if (orientation & (GLFMInterfaceOrientationPortrait | GLFMInterfaceOrientationPortraitUpsideDown)) {
+ if (!(global.orientation & (GLFMInterfaceOrientationPortrait | GLFMInterfaceOrientationPortraitUpsideDown))) {
+ swap_dimensions_and_send_resize(glfm);
+ }
+ } else if (orientation & (GLFMInterfaceOrientationLandscapeLeft | GLFMInterfaceOrientationLandscapeRight)) {
+ if (!(global.orientation & (GLFMInterfaceOrientationLandscapeLeft | GLFMInterfaceOrientationLandscapeRight))) {
+ swap_dimensions_and_send_resize(glfm);
+ }
}
+ global.orientation = orientation;
+}
+
+static u8 glfm_to_stela_touch[] = {
+ [GLFMTouchPhaseHover] = STELA_TOUCH_HOVER,
+ [GLFMTouchPhaseBegan] = STELA_TOUCH_BEGAN,
+ [GLFMTouchPhaseMoved] = STELA_TOUCH_MOVED,
+ [GLFMTouchPhaseEnded] = STELA_TOUCH_ENDED,
+ [GLFMTouchPhaseCancelled] = STELA_TOUCH_CANCELLED
+};
+
+static bool onTouch(GLFMDisplay *display, s32 touch, GLFMTouchPhase phase, f64 x, f64 y)
+{
+ struct stl_window_glfm *glfm = (struct stl_window_glfm *)glfmGetUserData(display);
+ stl_window_send_touch_event(&glfm->w, touch, glfm_to_stela_touch[phase], x, y);
+ return true;
}
void glfmMain(GLFMDisplay *display)
{
- nn_common_init();
+ nn_common_init("glfmMain");
stl_global_init(false);
global.display = display;
+#define STELA_INCLUDE_DEPTH_BUFFER
glfmSetDisplayConfig(display,
- GLFMRenderingAPIOpenGLES2,
+ GLFMRenderingAPIOpenGLES32,
GLFMColorFormatRGBA8888,
+#ifdef STELA_INCLUDE_DEPTH_BUFFER
+ GLFMDepthFormat24,
+ GLFMStencilFormat8,
+#else
GLFMDepthFormatNone,
GLFMStencilFormatNone,
+#endif
GLFMMultisampleNone);
+ global.orientation = glfmGetInterfaceOrientation(display);
+ glfmSetDisplayChrome(display, GLFMUserInterfaceChromeNone);
+ glfmSetMultitouchEnabled(display, true);
glfmSetSurfaceCreatedFunc(display, onSurfaceCreated);
- glfmSetSurfaceDestroyedFunc(display, onSurfaceDestroyed);
glfmSetRenderFunc(display, onDraw);
+ glfmSetSurfaceDestroyedFunc(display, onSurfaceDestroyed);
+ glfmSetOrientationChangedFunc(display, onOrientationChanged);
+ glfmSetTouchFunc(display, onTouch);
}
static bool window_glfm_create_window(struct stl_window *window, u32 width, u32 height,
diff --git a/src/window_glfm.h b/src/window_glfm.h
index f3703b9..bfbda04 100644
--- a/src/window_glfm.h
+++ b/src/window_glfm.h
@@ -7,6 +7,7 @@
struct stl_glfm_global {
GLFMDisplay *display;
bool did_main;
+ GLFMInterfaceOrientation orientation;
};
struct stl_window_glfm {
diff --git a/src/window_glfw.c b/src/window_glfw.c
index 5892bfb..b7b3b30 100644
--- a/src/window_glfw.c
+++ b/src/window_glfw.c
@@ -72,21 +72,31 @@ void stl_global_close(void)
glfwTerminate();
}
-static void key_callback(GLFWwindow *window, s32 key, s32 scancode, s32 action, s32 mods)
+static void resize_callback(GLFWwindow *window, s32 event_width, s32 event_height)
{
struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
- (void)scancode;
- (void)mods;
- al_assert(key >= 0 && key <= UINT16_MAX);
- if (key == GLFW_KEY_F25 || key == GLFW_KEY_WORLD_1 || key == GLFW_KEY_WORLD_2) {
- log_warn("Unmapped GLFW key pressed (%hu).", (u16)key);
+ if (event_width <= 0 || event_height <= 0) {
+ // This happens on Windows when minimizing.
return;
}
- u8 key_state = action == GLFW_PRESS ? STELA_BUTTON_PRESSED : STELA_BUTTON_RELEASED;
- if (glfw->w.key_immediate_callback) {
- glfw->w.key_immediate_callback(glfw->w.userdata, key_state, (u16)key);
+
+ u32 width = (u32)event_width;
+ u32 height = (u32)event_height;
+ if (width == glfw->w.width && height == glfw->w.height) {
+ return;
}
- stl_window_send_key_event(&glfw->w, key_state, (u16)key);
+
+ glfw->w.width = (u32)width;
+ glfw->w.height = (u32)height;
+
+ stl_window_send_resize_event(&glfw->w, glfw->w.width, glfw->w.height);
+}
+
+static void content_scale_callback(GLFWwindow *window, f32 xscale, f32 yscale)
+{
+ struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
+ glfw->scale_x = xscale;
+ glfw->scale_y = yscale;
}
static void cursor_position_callback(GLFWwindow *window, f64 xpos, f64 ypos)
@@ -97,6 +107,13 @@ static void cursor_position_callback(GLFWwindow *window, f64 xpos, f64 ypos)
stl_window_send_pointer_pos_event(&glfw->w, xpos, ypos);
}
+static void scroll_callback(GLFWwindow *window, f64 xoffset, f64 yoffset)
+{
+ struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
+ (void)xoffset;
+ stl_window_send_scroll_event(&glfw->w, -yoffset);
+}
+
static void mouse_button_callback(GLFWwindow *window, s32 button, s32 action, s32 mods)
{
struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
@@ -126,47 +143,20 @@ static void mouse_button_callback(GLFWwindow *window, s32 button, s32 action, s3
}
}
-static void scroll_callback(GLFWwindow *window, f64 xoffset, f64 yoffset)
-{
- struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
- (void)xoffset;
- stl_window_send_scroll_event(&glfw->w, -yoffset);
-}
-
-static void resize_callback(GLFWwindow *window, s32 event_width, s32 event_height)
+static void key_callback(GLFWwindow *window, s32 key, s32 scancode, s32 action, s32 mods)
{
struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
- if (event_width <= 0 || event_height <= 0) {
- // This happens on Windows when minimizing.
- return;
- }
-
- u32 width = (u32)event_width;
- u32 height = (u32)event_height;
- if (width == glfw->w.width && height == glfw->w.height) {
+ (void)scancode;
+ (void)mods;
+ al_assert(key >= 0 && key <= UINT16_MAX);
+ if (key == GLFW_KEY_F25 || key == GLFW_KEY_WORLD_1 || key == GLFW_KEY_WORLD_2) {
+ log_warn("Unmapped GLFW key pressed (%hu).", (u16)key);
return;
}
-
- glfw->w.width = (u32)width;
- glfw->w.height = (u32)height;
-
- stl_window_send_resize_event(&glfw->w, glfw->w.width, glfw->w.height);
-}
-
-static void content_scale_callback(GLFWwindow *window, f32 xscale, f32 yscale)
-{
- struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
- glfw->scale_x = xscale;
- glfw->scale_y = yscale;
-}
-
-#ifdef STELA_POLL_INLINE
-static void refresh_callback(GLFWwindow *window)
-{
- struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
- stl_window_send_refresh_event(&glfw->w);
+ u8 key_state = action == GLFW_PRESS ? STELA_BUTTON_PRESSED : STELA_BUTTON_RELEASED;
+ stl_window_send_key_immediate_event(&glfw->w, key_state, (u16)key);
+ stl_window_send_key_event(&glfw->w, key_state, (u16)key);
}
-#endif
static void close_callback(GLFWwindow *window)
{
@@ -264,17 +254,14 @@ static bool window_glfw_create_window(struct stl_window *window, u32 width, u32
glfwSetWindowUserPointer(glfw->window, glfw);
- glfwSetKeyCallback(glfw->window, key_callback);
- glfwSetCursorPosCallback(glfw->window, cursor_position_callback);
- glfwSetMouseButtonCallback(glfw->window, mouse_button_callback);
- glfwSetScrollCallback(glfw->window, scroll_callback);
//glfwSetFramebufferSizeCallback(glfw->window, resize_callback);
glfwSetWindowSizeCallback(glfw->window, resize_callback);
glfwSetWindowContentScaleCallback(glfw->window, content_scale_callback);
-#ifdef STELA_POLL_INLINE
- glfwSetWindowRefreshCallback(glfw->window, refresh_callback);
-#endif
- // This seems to be called if we block too long after creating a window.
+ glfwSetCursorPosCallback(glfw->window, cursor_position_callback);
+ glfwSetScrollCallback(glfw->window, scroll_callback);
+ glfwSetMouseButtonCallback(glfw->window, mouse_button_callback);
+ glfwSetKeyCallback(glfw->window, key_callback);
+ // A Wayland window will trigger CloseCallback if it's lagging too hard.
glfwSetWindowCloseCallback(glfw->window, close_callback);
return true;
@@ -367,6 +354,9 @@ static void window_glfw_toggle_fullscreen(struct stl_window *window)
}
#ifdef STELA_POLL_INLINE
+#ifdef STELA_EVENT_BUFFER
+#error "window_glfw_poll() is incompatible with event buffer mode."
+#endif
static bool window_glfw_poll(struct stl_window *window, bool block)
{
(void)window;
@@ -403,9 +393,6 @@ static void window_glfw_free(struct stl_window **window)
if (glfw->window) {
glfwDestroyWindow(glfw->window);
}
-#ifdef STELA_EVENT_BUFFER
- al_free(glfw->w.data);
-#endif
al_free(glfw);
*window = NULL;
}
diff --git a/src/window_kms.c b/src/window_kms.c
index 93192e6..15d1532 100644
--- a/src/window_kms.c
+++ b/src/window_kms.c
@@ -1,4 +1,5 @@
#include "window_kms.h"
+#include "common.h"
void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata)
{
diff --git a/src/window_wayland.c b/src/window_wayland.c
index 1ed597d..530daf2 100644
--- a/src/window_wayland.c
+++ b/src/window_wayland.c
@@ -567,9 +567,7 @@ static void keyboard_key(void *data, struct wl_keyboard *keyboard,
}
u8 key_state = state == WL_KEYBOARD_KEY_STATE_PRESSED ? STELA_BUTTON_PRESSED : STELA_BUTTON_RELEASED;
- if (wl->w.key_immediate_callback) {
- wl->w.key_immediate_callback(wl->w.userdata, key_state, global.keycodes[key]);
- }
+ stl_window_send_key_immediate_event(&wl->w, key_state, global.keycodes[key]);
stl_window_send_key_event(&wl->w, key_state, global.keycodes[key]);
}
@@ -1040,7 +1038,7 @@ static void window_wayland_set_decorations(struct stl_window *window, bool enabl
u32 mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
zxdg_toplevel_decoration_v1_set_mode(wl->zxdg_toplevel_decoration, mode);
wl->decorated = false;
- } else if (!wl->decorated) {
+ } else if (enabled && !wl->decorated) {
u32 mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
zxdg_toplevel_decoration_v1_set_mode(wl->zxdg_toplevel_decoration, mode);
wl->decorated = true;
@@ -1116,18 +1114,45 @@ void window_wayland_free(struct stl_window **window)
if (wl->layer_shell) zwlr_layer_shell_v1_destroy(wl->layer_shell);
if (wl->compositor) wl_compositor_destroy(wl->compositor);
#ifdef STELA_API_OPENGL
- if (stl_egl_is_ready(&wl->egl)) {
- stl_egl_destroy_context(&wl->egl);
- }
-#endif
-#ifdef STELA_EVENT_BUFFER
- al_free(wl->w.data);
+ if (stl_egl_is_ready(&wl->egl)) stl_egl_destroy_context(&wl->egl);
#endif
al_free(wl);
*window = NULL;
}
-#ifdef STELA_API_OPENGL
+#if defined STELA_API_VULKAN
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_vk_proc_address(VkInstance inst, const char *name)
+{
+ void *vk_module = dlopen("libvulkan.so.1", RTLD_LAZY | RTLD_LOCAL);
+ if (!vk_module) return NULL;
+ PFN_vkVoidFunction vk_get_proc_addr = dlsym(vk_module, "vkGetInstanceProcAddr");
+ if (!vk_get_proc_addr) return NULL;
+ return (PFN_vkVoidFunction)vk_get_proc_addr(inst, name);
+}
+
+static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL window_win32_get_vk_proc_address(VkInstance inst, const char *name)
+{
+ if (strcmp(name, "vkGetInstanceProcAddr") == 0) {
+ return (PFN_vkVoidFunction)vk_get_proc_addr;
+ }
+ return vk_get_proc_addr(inst, name);
+}
+
+static VkResult window_win32_vk_create_surface(void *window, VkInstance inst, VkSurfaceKHR *surface)
+{
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
+ (void)w32;
+ (void)inst;
+ (void)surface;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+}
+
+static const char *const *window_win32_vk_get_extensions(u32 *num)
+{
+ (void)num;
+ return NULL;
+}
+#elif defined STELA_API_OPENGL
static bool window_wayland_gl_loader_load(void *window)
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)window;
diff --git a/src/window_win32.c b/src/window_win32.c
index 7edee49..f4baca8 100644
--- a/src/window_win32.c
+++ b/src/window_win32.c
@@ -8,6 +8,17 @@
#ifdef STELA_API_OPENGL
#include "gl_common.h"
+// https://registry.khronos.org/OpenGL/api/GL/wgl.h
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+
#define STELA_GL_API 1
#define STELA_GLES_API 2
@@ -728,9 +739,7 @@ static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam,
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
- if (w32->w.key_immediate_callback) {
- w32->w.key_immediate_callback(w32->w.userdata, MESSAGE_TO_KEY_STATE(Message), Global.keycodes[WParam]);
- }
+ stl_window_send_key_immediate_event(&w32->w, MESSAGE_TO_KEY_STATE(Message), Global.keycodes[WParam]);
goto intercept;
case WM_SIZE:
goto intercept;
@@ -890,6 +899,7 @@ static bool window_win32_create_window(struct stl_window *window, u32 width, u32
stl_window_created(&w32->w, width, height, flags);
w32->Decorated = TRUE;
+ w32->UserDecorated = TRUE;
w32->Prev.Style = GetWindowLong(w32->Window, GWL_STYLE);
w32->WindowMoving = FALSE;
w32->MouseButtonMask = 0;
@@ -938,7 +948,7 @@ static void set_window_decorations(struct stl_window_win32 *w32, bool enabled)
Style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
SetWindowLong(w32->Window, GWL_STYLE, Style);
w32->Decorated = FALSE;
- } else if (!w32->Decorated) {
+ } else if (enabled && !w32->Decorated) {
al_assert(w32->Prev.Style != 0);
SetWindowLong(w32->Window, GWL_STYLE, w32->Prev.Style);
w32->Decorated = TRUE;
@@ -966,7 +976,9 @@ static void window_win32_toggle_fullscreen(struct stl_window *window)
struct stl_monitor_win32 *Monitor = w32->Prev.Monitor;
s32 X = w32->Prev.X - Monitor->X;
s32 Y = w32->Prev.Y - Monitor->Y;
- set_window_decorations(w32, true);
+ if (w32->UserDecorated) {
+ set_window_decorations(w32, true);
+ }
ShowCursor(TRUE);
SetWindowPos(w32->Window, HWND_NOTOPMOST, X, Y, w32->Prev.Width, w32->Prev.Height, SWP_FRAMECHANGED);
}
@@ -976,9 +988,12 @@ static void window_win32_toggle_fullscreen(struct stl_window *window)
static void window_win32_set_decorations(struct stl_window *window, bool enabled)
{
struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
- set_window_decorations(w32, enabled);
- UINT Flags = SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE;
- SetWindowPos(w32->Window, 0, 0, 0, 0, 0, Flags);
+ w32->UserDecorated = enabled;
+ if (!w32->w.fullscreen) {
+ set_window_decorations(w32, enabled);
+ UINT Flags = SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE;
+ SetWindowPos(w32->Window, 0, 0, 0, 0, 0, Flags);
+ }
}
static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
@@ -1076,6 +1091,9 @@ static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
}
#ifdef STELA_POLL_INLINE
+#ifdef STELA_EVENT_BUFFER
+#error "window_win32_poll() is incompatible with event buffer mode."
+#endif
static bool window_win32_poll(struct stl_window *window, bool block)
{
struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
@@ -1117,9 +1135,6 @@ static void window_win32_free(struct stl_window **window)
struct stl_window_win32 *w32 = (struct stl_window_win32 *)*window;
SendMessageW(Global.ServiceWindow, DESTROY_DANGEROUS_WINDOW, (WPARAM)w32->Window, 0);
al_wstr_free(&w32->WindowName);
-#ifdef STELA_EVENT_BUFFER
- al_free(wl->w.data);
-#endif
al_free(w32);
*window = NULL;
}
@@ -1129,8 +1144,7 @@ static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetVKProcAddress(VkInstance Inst
{
HMODULE VKModule = LoadLibraryA("vulkan-1.dll");
PFN_vkGetInstanceProcAddr GetInstanceProcAddr = (void *)GetProcAddress(VKModule, "vkGetInstanceProcAddr");
- PFN_vkVoidFunction proc = (PFN_vkVoidFunction)GetInstanceProcAddr(Inst, Name);
- return proc;
+ return (PFN_vkVoidFunction)GetInstanceProcAddr(Inst, Name);
}
static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL window_win32_get_vk_proc_address(VkInstance inst, const char *name)
diff --git a/src/window_win32.h b/src/window_win32.h
index 35b0dc5..5fbb0f3 100644
--- a/src/window_win32.h
+++ b/src/window_win32.h
@@ -46,6 +46,7 @@ struct stl_window_win32 {
LONG Style;
} Prev;
BOOL Decorated;
+ BOOL UserDecorated;
BOOL WindowMoving;
POINTS LastMousePos;
u32 MouseButtonMask;
diff --git a/src/window_x11.c b/src/window_x11.c
index 0d8d870..06b6d51 100644
--- a/src/window_x11.c
+++ b/src/window_x11.c
@@ -253,9 +253,7 @@ static void handle_next_xevent(struct stl_window_x11 *xw)
case KeyPress:
case KeyRelease: {
u8 key_state = xev.type == KeyPress ? STELA_BUTTON_PRESSED : STELA_BUTTON_RELEASED;
- if (xw->w.key_immediate_callback) {
- xw->w.key_immediate_callback(xw->w.userdata, key_state, xev.xkey.keycode);
- }
+ stl_window_send_key_immediate_event(&xw->w, key_state, xev.xkey.keycode);
stl_window_send_key_event(&xw->w, key_state, xev.xkey.keycode);
break;
}
@@ -307,9 +305,6 @@ static void window_x11_free(struct stl_window **window)
{
struct stl_window_x11 *xw = (struct stl_window_x11 *)*window;
// @TODO: Cleanup x11 stuff.
-#ifdef STELA_EVENT_BUFFER
- al_free(xw->w.data);
-#endif
al_free(xw);
*window = NULL;
}
diff --git a/subprojects/libalabaster.wrap b/subprojects/libalabaster.wrap
index 243dff8..81771ed 100644
--- a/subprojects/libalabaster.wrap
+++ b/subprojects/libalabaster.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libalabaster
-revision = ec99011aca3a9b92964c653d74d693e693ac052f
+revision = b403770e7eb6e0a5a8ca14a24f91dbf214ffe917
depth = 1
diff --git a/subprojects/libnaunet.wrap b/subprojects/libnaunet.wrap
index 3f43502..8388a93 100644
--- a/subprojects/libnaunet.wrap
+++ b/subprojects/libnaunet.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libnaunet
-revision = 6993b9814769668fb03b4d282734f20f63b16f9c
+revision = 393e266f6bfceb25a97cd1cf28dfc72cac9e9f81
depth = 1