summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-09-19 15:06:37 -0400
committerAndrew Opalach <andrew@akon.city> 2024-09-19 15:06:37 -0400
commit72e52678a96c8f9350a992a062afb1c11e685102 (patch)
tree935f3d1060631bafd2a859c37eb1faaffbbd53db
parentba024a75640d2856ae0ed9350dd32f115c6b2f15 (diff)
downloadstela-72e52678a96c8f9350a992a062afb1c11e685102.tar.gz
stela-72e52678a96c8f9350a992a062afb1c11e685102.tar.bz2
stela-72e52678a96c8f9350a992a062afb1c11e685102.zip
Initial global context/multiple window support
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--.gitignore3
-rw-r--r--meson.build17
-rw-r--r--src/egl_common.c76
-rw-r--r--src/egl_common.h12
-rw-r--r--src/gl_common.c5
-rw-r--r--src/gl_common.h5
-rw-r--r--src/poll_common.c2
-rw-r--r--src/stela.c27
-rw-r--r--src/window.h7
-rw-r--r--src/window_glfw.c67
-rw-r--r--src/window_glfw.h8
-rw-r--r--src/window_wayland.c498
-rw-r--r--src/window_wayland.h23
-rw-r--r--src/window_x11.c47
-rw-r--r--src/window_x11.h7
-rw-r--r--subprojects/glfw3.wrap2
16 files changed, 369 insertions, 437 deletions
diff --git a/.gitignore b/.gitignore
index 6a6e718..cd344ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
+.cache/
build*/
compile_commands.json
-.cache/
-.clangd/
subprojects/c89atomic.wrap
subprojects/glad/
subprojects/libakiyo
diff --git a/meson.build b/meson.build
index 38b202f..4fb67f9 100644
--- a/meson.build
+++ b/meson.build
@@ -5,6 +5,7 @@ compiler = meson.get_compiler('c')
cmake = import('cmake')
is_debug = get_option('buildtype').startswith('debug')
+is_minsize = get_option('buildtype') == 'minsize'
is_linux = host_machine.system() == 'linux'
is_windows = host_machine.system() == 'windows'
@@ -13,7 +14,7 @@ is_macos = host_machine.system() == 'darwin'
alabaster = subproject('libalabaster').get_variable('alabaster')
akiyo = subproject('libakiyo', default_options: ['event-loop=disabled']).get_variable('akiyo')
-stela_src = ['src/stela.c', 'src/window.c']
+stela_src = ['src/window.c']
stela_inc = [include_directories('include')]
stela_deps = [alabaster, akiyo]
stela_args = []
@@ -40,12 +41,18 @@ if get_option('api') == 'null'
stela_args += ['-DSTELA_API_NULL']
elif get_option('api') == 'opengl'
use_glad = false
+ use_gles = false
if use_glad
- stela_deps += [subproject('glad').get_variable('glad')]
+ stela_deps += [subproject('glad', default_options: [
+ use_gles ? 'use_gles=true' : 'use_gles=false'
+ ]).get_variable('glad')]
stela_args += ['-DSTELA_USE_GLAD']
else
stela_deps += [dependency('gl')]
endif
+ if use_gles
+ stela_args += ['-DSTELA_USE_GLES']
+ endif
stela_src += ['src/gl_common.c']
stela_args += ['-DSTELA_API_OPENGL']
if get_option('window') in ['x11', 'wayland']
@@ -64,10 +71,11 @@ elif get_option('api') == 'vulkan'
endif
if get_option('window') == 'glfw'
- glfw3 = dependency('glfw3', required: false, allow_fallback: true)
+ glfw3 = dependency('glfw3', required: false, allow_fallback: false)
if not glfw3.found()
glfw_opts = cmake.subproject_options()
- glfw_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : 'Release' })
+ reltype = is_minsize ? 'MinSizeRel' : 'Release'
+ glfw_opts.add_cmake_defines({ 'CMAKE_BUILD_TYPE': is_debug ? 'Debug' : reltype })
glfw_opts.add_cmake_defines({ 'GLFW_INSTALL': false })
glfw_opts.add_cmake_defines({ 'GLFW_BUILD_EXAMPLES': false })
glfw_opts.add_cmake_defines({ 'GLFW_BUILD_TESTS': false })
@@ -102,7 +110,6 @@ elif get_option('window') == 'wayland'
if not wlr_protocols.found()
wlr_protocols_datadir = subproject('wlr-protocols').get_variable('wlr_protocols_srcdir')
else
- # Untested
wlr_protocols_datadir = wlr_protocols.get_variable(pkgconfig: 'pkgdatadir')
endif
scanner = find_program('wayland-scanner')
diff --git a/src/egl_common.c b/src/egl_common.c
index dbde5da..7fd8ddb 100644
--- a/src/egl_common.c
+++ b/src/egl_common.c
@@ -16,6 +16,44 @@
PASTE_GL_VERSIONS()
+bool stl_maybe_load_egl(void)
+{
+#ifdef STELA_USE_GLAD
+ s32 egl_version = gladLoaderLoadEGL(NULL);
+ if (!egl_version) {
+ al_log_error("egl", "Failed to pre-load EGL (glad).");
+ return false;
+ }
+#endif
+ return true;
+}
+
+bool stl_load_egl(struct stl_egl_global *global)
+{
+ s32 minor, major;
+ if (!eglInitialize(global->display, &major, &minor)) {
+ al_log_error("egl", "Failed to initialize.");
+ return false;
+ }
+ al_log_info("egl", "Initialized EGL version %i.%i.", major, minor);
+
+#ifdef STELA_USE_GLAD
+ s32 egl_version = gladLoaderLoadEGL(global->display);
+ if (!egl_version) {
+ al_log_error("egl", "Failed to load EGL (glad).");
+ return false;
+ }
+#endif
+ al_log_info("egl", "Using EGL (glad) version %s.", eglQueryString(global->display, EGL_VERSION));
+
+ return true;
+}
+
+void stl_terminate_egl(struct stl_egl_global *global)
+{
+ eglTerminate(global->display);
+}
+
// https://gitlab.freedesktop.org/mesa/kmscube/-/blob/master/common.c#L162
static s32 match_config_to_visual(EGLDisplay display, EGLint visual_id, EGLConfig *configs, s32 count)
{
@@ -62,40 +100,11 @@ out:
return index != -1;
}
-bool stl_maybe_load_egl(struct stl_egl *egl)
+bool stl_init_egl_context(struct stl_egl *egl, struct stl_egl_global *global, EGLint visual_id, EGLConfig *config)
{
- (void)egl;
-#ifdef STELA_USE_GLAD
- s32 egl_version = gladLoaderLoadEGL(NULL);
- if (!egl_version) {
- al_log_error("egl", "Failed to pre-load EGL (glad).");
- return false;
- }
-#endif
- return true;
-}
-
-bool stl_init_egl(struct stl_egl *egl, EGLint visual_id, EGLConfig *config)
-{
- s32 minor, major;
- if (!eglInitialize(egl->display, &major, &minor)) {
- al_log_error("egl", "Failed to initialize.");
- return false;
- }
- al_log_info("egl", "Initialized EGL version %i.%i.", major, minor);
-
-#ifdef STELA_USE_GLAD
- s32 egl_version = gladLoaderLoadEGL(egl->display);
- if (!egl_version) {
- al_log_error("egl", "Failed to load EGL (glad).");
- return false;
- }
-#endif
-
- al_log_info("egl", "Using EGL (glad) version %s.", eglQueryString(egl->display, EGL_VERSION));
+ egl->display = global->display;
egl->context = EGL_NO_CONTEXT;
-
for (u32 i = 0; i < AL_ARRAY_SIZE(stl_gl_vers); i++) {
const EGLint context_attr_gles[] = {
EGL_CONTEXT_CLIENT_VERSION, stl_gl_vers[i].major,
@@ -190,11 +199,6 @@ void stl_egl_destroy_context(struct stl_egl *egl)
eglDestroyContext(egl->display, egl->context);
}
-void stl_egl_terminate(struct stl_egl *egl)
-{
- eglTerminate(egl->display);
-}
-
#define ERROR_CASE_STR(value) case value: return #value;
static const char *eglGetErrorString(EGLint error)
{
diff --git a/src/egl_common.h b/src/egl_common.h
index fabb2ef..1184eed 100644
--- a/src/egl_common.h
+++ b/src/egl_common.h
@@ -9,14 +9,21 @@
#include <EGL/eglext.h>
#endif
+struct stl_egl_global {
+ EGLDisplay display;
+};
+
struct stl_egl {
EGLDisplay display;
EGLSurface surface;
EGLContext context;
};
-bool stl_maybe_load_egl(struct stl_egl *egl);
-bool stl_init_egl(struct stl_egl *egl, EGLint visual_id, EGLConfig *config);
+bool stl_maybe_load_egl(void);
+bool stl_load_egl(struct stl_egl_global *global);
+void stl_terminate_egl(struct stl_egl_global *global);
+
+bool stl_init_egl_context(struct stl_egl *egl, struct stl_egl_global *global, EGLint visual_id, EGLConfig *config);
void stl_egl_make_current(struct stl_egl *egl);
void stl_egl_release_current(struct stl_egl *egl);
void stl_egl_swap_interval(struct stl_egl *egl, s32 interval);
@@ -24,6 +31,5 @@ void stl_egl_swap_buffers(struct stl_egl *egl);
bool stl_egl_is_ready(struct stl_egl *egl);
void stl_egl_destroy_surface(struct stl_egl *egl);
void stl_egl_destroy_context(struct stl_egl *egl);
-void stl_egl_terminate(struct stl_egl *egl);
void stl_egl_check_error();
diff --git a/src/gl_common.c b/src/gl_common.c
index 51118b3..59a1ab0 100644
--- a/src/gl_common.c
+++ b/src/gl_common.c
@@ -18,12 +18,15 @@ static const char *glGetErrorString(GLenum error)
}
#undef ERROR_CASE_STR
-void stl_gl_check_error()
+bool stl_gl_check_error()
{
GLenum error;
+ bool any_error = false;
while ((error = glGetError()) != GL_NO_ERROR) {
al_log_error("egl", "GL error %s, %d.", glGetErrorString(error), error);
+ any_error = true;
}
+ return any_error;
}
bool stl_gl_loader_load(void (*(*get_proc_address)(const char *))(void))
diff --git a/src/gl_common.h b/src/gl_common.h
index 57eb5e5..bef0a75 100644
--- a/src/gl_common.h
+++ b/src/gl_common.h
@@ -1,6 +1,3 @@
-//#define STELA_USE_GLAD
-//#define STELA_USE_GLES
-
#include <al/types.h>
#ifdef STELA_USE_GLAD
@@ -20,5 +17,5 @@
#endif
#endif
-void stl_gl_check_error();
+bool stl_gl_check_error();
bool stl_gl_loader_load(void (*(*get_proc_address)(const char *))(void));
diff --git a/src/poll_common.c b/src/poll_common.c
index 9255ad9..4174dae 100644
--- a/src/poll_common.c
+++ b/src/poll_common.c
@@ -22,6 +22,7 @@ bool stl_poll_common(struct aki_pollfd *fds, bool block)
if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { // Fatal error.
al_log_error("poll_common", "poll() returned error in revents (%d).", fds[0].revents);
+ al_assert(false);
exit(0);
return false;
}
@@ -54,6 +55,7 @@ bool stl_process_events_common(struct aki_pollfd *fds)
#endif
return (fds[0].revents & POLLIN);
#elif defined STELA_POLL_FD
+ (void)fds;
return true;
#endif
}
diff --git a/src/stela.c b/src/stela.c
deleted file mode 100644
index 8203da4..0000000
--- a/src/stela.c
+++ /dev/null
@@ -1,27 +0,0 @@
-#include <al/log.h>
-
-#include "window.h"
-
-#if defined STELA_WINDOW_WAYLAND
-#include "window_wayland.h"
-#elif defined STELA_WINDOW_X11
-#include "window_x11.h"
-#elif defined STELA_WINDOW_GLFW
-#include "window_glfw.h"
-#endif
-
-#if defined STELA_WINDOW_WAYLAND || defined STELA_WINDOW_X11 || defined STELA_WINDOW_GLFW
-struct stl_window *stl_window_create(void)
-{
-#if defined STELA_WINDOW_WAYLAND
- al_log_info("stela", "Creating wayland (EGL) window.");
- return stl_window_wayland_create();
-#elif defined STELA_WINDOW_X11
- al_log_info("stela", "Creating X11 (EGL) window.");
- return stl_window_x11_create();
-#elif defined STELA_WINDOW_GLFW
- al_log_info("stela", "Creating GLFW3 window.");
- return stl_window_glfw_create();
-#endif
-}
-#endif
diff --git a/src/window.h b/src/window.h
index 7919983..88cbb14 100644
--- a/src/window.h
+++ b/src/window.h
@@ -38,7 +38,6 @@ enum {
#define STELA_MAX_MONITOR_NAME 255u
-struct stl_window;
struct stl_monitor {
u32 x;
u32 y;
@@ -47,7 +46,6 @@ struct stl_monitor {
s32 scale;
bool vertical;
char name[STELA_MAX_MONITOR_NAME];
- struct stl_window *window;
};
struct stl_window {
@@ -55,7 +53,6 @@ struct stl_window {
s32 height;
s32 scale;
bool fullscreen;
- array(struct stl_monitor *) monitors;
#if defined STELA_EVENT_BUFFER
u8 *data;
// Render thread events.
@@ -136,7 +133,11 @@ enum {
#define STELA_EVENTS_SIZE (STELA_EVENT_SIZE * 288)
#endif
+void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata);
+bool stl_global_init(void);
+void stl_global_close(void);
struct stl_window *stl_window_create(void);
+
void stl_window_send_pointer_pos_event(struct stl_window *window, 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);
diff --git a/src/window_glfw.c b/src/window_glfw.c
index 7697729..41e6172 100644
--- a/src/window_glfw.c
+++ b/src/window_glfw.c
@@ -20,6 +20,36 @@
PASTE_GL_VERSIONS()
#endif
+static struct stl_glfw_global global;
+
+void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata)
+{
+ (void)output_discovered;
+ (void)userdata;
+}
+
+static void error_callback(s32 error_code, const char *description)
+{
+ al_log_error("glfw", "GLFW Error %d: %s.", error_code, description);
+}
+
+bool stl_global_init(void)
+{
+ glfwSetErrorCallback(error_callback);
+ if (!glfwInit()) {
+ al_log_error("glfw", "Failed to initialize GLFW.");
+ return false;
+ }
+ global.master_window = NULL;
+ al_log_info("glfw", "Successfully initialized GLFW.");
+ return true;
+}
+
+void stl_global_close(void)
+{
+ glfwTerminate();
+}
+
static void key_callback(GLFWwindow *window, s32 key, s32 scancode, s32 action, s32 mods)
{
struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
@@ -86,11 +116,6 @@ static bool window_glfw_create_window(struct stl_window *window, s32 width, s32
struct stl_window_glfw *glfw = (struct stl_window_glfw *)window;
(void)monitor;
- if (!glfwInit()) {
- al_log_error("window_glfw", "Failed to initialize GLFW.");
- return false;
- }
-
#if defined STELA_API_VULKAN || defined STELA_API_DX11
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
#elif defined STELA_API_OPENGL
@@ -107,28 +132,34 @@ static bool window_glfw_create_window(struct stl_window *window, s32 width, s32
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
}
#endif
- al_log_info("glfw", "Trying to make a %s context of version %i.%i (GLSL %i).",
+ al_log_info("window_glfw", "Trying to make a %s context of version %i.%i (GLSL %i).",
stl_gl_vers[i].api == STELA_GL_API ? "GL" : "GLES",
stl_gl_vers[i].major, stl_gl_vers[i].minor, stl_gl_vers[i].glsl_ver);
#endif
- glfw->window = glfwCreateWindow(width, height, name, NULL, NULL);
+ glfw->window = glfwCreateWindow(width, height, name, NULL, global.master_window);
#if defined STELA_API_OPENGL
if (glfw->window) {
- al_log_info("glfw", "Context successfully created.");
+ al_log_info("window_glfw", "Context successfully created.");
break;
}
}
#endif
if (!glfw->window) {
- al_log_info("glfw", "Failed to create window.");
- glfwTerminate();
+ al_log_info("window_glfw", "Failed to create window.");
return false;
}
+ // This doesn't work right, at least on wayland.
+ if (!global.master_window) global.master_window = glfw->window;
+
+#if defined STELA_API_OPENGL
glfwMakeContextCurrent(glfw->window);
glfwSwapInterval((flags & STELA_WINDOW_VSYNC) ? 1 : 0);
glfwMakeContextCurrent(NULL);
+#else
+ (void)flags;
+#endif
glfwGetFramebufferSize(glfw->window, &glfw->w.width, &glfw->w.height);
glfwSetWindowSizeLimits(glfw->window, STELA_MIN_WIDTH, STELA_MIN_HEIGHT, GLFW_DONT_CARE, GLFW_DONT_CARE);
@@ -199,16 +230,16 @@ static void window_glfw_toggle_fullscreen(struct stl_window *window)
{
struct stl_window_glfw *glfw = (struct stl_window_glfw *)window;
if (!glfw->w.fullscreen) {
- glfwGetWindowPos(glfw->window, &glfw->prev_state.x, &glfw->prev_state.y);
- glfw->prev_state.width = glfw->w.width;
- glfw->prev_state.height = glfw->w.height;
+ glfwGetWindowPos(glfw->window, &glfw->prev.x, &glfw->prev.y);
+ glfw->prev.width = glfw->w.width;
+ glfw->prev.height = glfw->w.height;
GLFWmonitor *monitor = get_current_monitor(glfw->window);
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(glfw->window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
//glfwSetInputMode(glfw->window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
} else {
- glfwSetWindowMonitor(glfw->window, NULL, glfw->prev_state.x, glfw->prev_state.y,
- glfw->prev_state.width, glfw->prev_state.height, GLFW_DONT_CARE);
+ glfwSetWindowMonitor(glfw->window, NULL, glfw->prev.x, glfw->prev.y,
+ glfw->prev.width, glfw->prev.height, GLFW_DONT_CARE);
//glfwSetInputMode(glfw->window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
}
glfw->w.fullscreen = !glfw->w.fullscreen;
@@ -256,12 +287,10 @@ static void window_glfw_free(struct stl_window **window)
struct stl_window_glfw *glfw = (struct stl_window_glfw *)*window;
if (glfw->window) {
glfwDestroyWindow(glfw->window);
- glfwTerminate();
}
#if defined STELA_EVENT_BUFFER
al_free(glfw->w.data);
#endif
- al_array_free(glfw->w.monitors);
al_free(glfw);
*window = NULL;
}
@@ -312,8 +341,9 @@ static void window_glfw_gl_swap_buffers(void *data)
}
#endif
-struct stl_window *stl_window_glfw_create(void)
+struct stl_window *stl_window_create(void)
{
+ al_log_info("stela", "Creating GLFW3 window.");
struct stl_window_glfw *glfw = al_alloc_object(struct stl_window_glfw);
#if defined STELA_EVENT_BUFFER
glfw->w.data = al_malloc(STELA_EVENTS_SIZE);
@@ -323,7 +353,6 @@ struct stl_window *stl_window_glfw_create(void)
glfw->w.pending_refresh = true;
#endif
glfw->w.fullscreen = false;
- al_array_init(glfw->w.monitors);
glfw->w.create_context = NULL;
glfw->w.create_window = window_glfw_create_window;
glfw->w.resize = window_glfw_resize;
diff --git a/src/window_glfw.h b/src/window_glfw.h
index 2810f2c..90d251f 100644
--- a/src/window_glfw.h
+++ b/src/window_glfw.h
@@ -13,6 +13,10 @@
#include "window.h"
+struct stl_glfw_global {
+ GLFWwindow *master_window;
+};
+
struct stl_window_glfw {
struct stl_window w;
GLFWwindow *window;
@@ -21,7 +25,5 @@ struct stl_window_glfw {
s32 y;
s32 width;
s32 height;
- } prev_state;
+ } prev;
};
-
-struct stl_window *stl_window_glfw_create(void);
diff --git a/src/window_wayland.c b/src/window_wayland.c
index fdb072f..c839e4b 100644
--- a/src/window_wayland.c
+++ b/src/window_wayland.c
@@ -5,6 +5,161 @@
#include "common.h"
#include "poll_common.h"
+static struct stl_wayland_global global;
+
+static void handle_output_geometry(void *data, struct wl_output *output,
+ s32 x, s32 y, s32 width_mm, s32 height_mm, s32 subpixel,
+ const char *make, const char *model, s32 transform)
+{
+ struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
+ (void)output;
+ (void)x;
+ (void)y;
+ (void)width_mm;
+ (void)height_mm;
+ (void)subpixel;
+ (void)make;
+ (void)model;
+ switch (transform) {
+ case WL_OUTPUT_TRANSFORM_90:
+ case WL_OUTPUT_TRANSFORM_270:
+ monitor->m.vertical = true;
+ break;
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ case WL_OUTPUT_TRANSFORM_180:
+ default:
+ monitor->m.vertical = false;
+ break;
+ }
+}
+
+static void handle_output_mode(void *data, struct wl_output *output,
+ u32 flags, s32 width, s32 height, s32 refresh)
+{
+ struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
+ (void)output;
+ (void)flags;
+ (void)refresh;
+ al_assert(width >= 0 && height >= 0);
+ if (monitor->m.vertical) {
+ monitor->m.width = (u32)height;
+ monitor->m.height = (u32)width;
+ } else {
+ monitor->m.width = (u32)width;
+ monitor->m.height = (u32)height;
+ }
+}
+
+static void handle_output_done(void *data, struct wl_output *output)
+{
+ struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
+ (void)output;
+ al_log_info("window_wayland", "Output discovered: %s (%ux%u) (vertical: %s).",
+ monitor->m.name, monitor->m.width, monitor->m.height, AL_BOOLSTR(monitor->m.vertical));
+ if (global.output_discovered) {
+ global.output_discovered(global.userdata, (struct stl_monitor *)monitor);
+ }
+}
+
+static void handle_output_scale(void *data, struct wl_output *output, s32 factor)
+{
+ struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
+ (void)output;
+ monitor->m.scale = factor;
+}
+
+static void handle_output_description(void *data, struct wl_output *output, const char *description)
+{
+ (void)data;
+ (void)output;
+ (void)description;
+}
+
+static void handle_output_name(void *data, struct wl_output *output, const char *name)
+{
+ struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
+ (void)output;
+ size_t len = strlen(name) + 1;
+ al_memcpy(monitor->m.name, name, AL_MIN(len, STELA_MAX_MONITOR_NAME));
+}
+
+static const struct wl_output_listener output_listener = {
+ .geometry = handle_output_geometry,
+ .mode = handle_output_mode,
+ .done = handle_output_done,
+ .scale = handle_output_scale,
+ .description = handle_output_description,
+ .name = handle_output_name
+};
+
+static void global_add(void *data, struct wl_registry *registry, u32 name,
+ const char *interface, u32 version)
+{
+ (void)data;
+ if (strcmp(interface, wl_output_interface.name) == 0) {
+ struct stl_monitor_wayland *monitor = al_alloc_object(struct stl_monitor_wayland);
+ al_array_push(global.monitors, (struct stl_monitor *)monitor);
+ monitor->output = wl_registry_bind(registry, name, &wl_output_interface, AL_MIN(4u, version));
+ wl_output_add_listener(monitor->output, &output_listener, monitor);
+ }
+}
+
+static void global_remove(void *data, struct wl_registry *registry, u32 name)
+{
+ (void)data;
+ (void)registry;
+ (void)name;
+}
+
+static const struct wl_registry_listener registry_listener = {
+ .global = global_add,
+ .global_remove = global_remove
+};
+
+void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata)
+{
+ global.output_discovered = output_discovered;
+ global.userdata = userdata;
+}
+
+bool stl_global_init(void)
+{
+ global.display = wl_display_connect(NULL);
+ if (!global.display) {
+ al_log_error("wayland", "Failed to connect to the display.");
+ return false;
+ }
+#if defined STELA_API_OPENGL
+ if (!stl_maybe_load_egl()) return false;
+ global.egl.display = eglGetDisplay((EGLNativeDisplayType)global.display);
+ if (!global.egl.display) {
+ al_log_error("wayland", "Failed to get wayland-native EGL display.");
+ return false;
+ }
+ if (!stl_load_egl(&global.egl)) return false;
+#endif
+ al_array_init(global.monitors);
+ global.registry = wl_display_get_registry(global.display);
+ wl_registry_add_listener(global.registry, &registry_listener, NULL);
+ wl_display_roundtrip(global.display);
+ wl_display_roundtrip(global.display);
+ global.active_surface = NULL;
+ return true;
+}
+
+void stl_global_close(void)
+{
+#if defined STELA_API_OPENGL
+ stl_terminate_egl(&global.egl);
+#endif
+ for (u32 i = 0; i < global.monitors.size; i++) {
+ struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)al_array_at(global.monitors, i);
+ if (monitor->output) wl_output_destroy(monitor->output);
+ al_free(monitor);
+ }
+ wl_display_disconnect(global.display);
+}
+
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, u32 serial)
{
(void)data;
@@ -20,12 +175,10 @@ static void pointer_enter(void *data, struct wl_pointer *pointer,
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
(void)pointer;
- (void)surface;
+ global.active_surface = surface;
if (wl->cursor_shape_device) {
wp_cursor_shape_device_v1_set_shape(wl->cursor_shape_device, serial, WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
}
- (void)surface_x;
- (void)surface_y;
wl->pointer_x = wl_fixed_to_double(surface_x) * wl->w.scale;
wl->pointer_y = wl_fixed_to_double(surface_y) * wl->w.scale;
}
@@ -43,6 +196,7 @@ static void pointer_motion(void *data, struct wl_pointer *pointer,
u32 time, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
+ if (wl->surface != global.active_surface) return;
(void)pointer;
(void)time;
wl->pointer_x += wl_fixed_to_double(surface_x) * wl->w.scale;
@@ -55,6 +209,7 @@ static void pointer_button(void *data, struct wl_pointer *pointer,
struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
(void)pointer;
(void)time;
+ if (wl->surface != global.active_surface) return;
#define MOUSE1 0x110
#define MOUSE2 0x111
#define MOUSE3 0x112
@@ -89,6 +244,7 @@ static void pointer_axis(void *data, struct wl_pointer *pointer,
struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
(void)pointer;
(void)time;
+ if (wl->surface != global.active_surface) return;
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
wl->scroll_y += wl_fixed_to_double(value);
} else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
@@ -99,8 +255,8 @@ static void pointer_axis(void *data, struct wl_pointer *pointer,
static void pointer_frame(void *data, struct wl_pointer *pointer)
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
- (void)wl;
(void)pointer;
+ if (wl->surface != global.active_surface) return;
if (wl->pointer_x || wl->pointer_y) {
stl_window_send_pointer_pos_event(&wl->w, wl->pointer_x, wl->pointer_y);
wl->pointer_x = 0.0;
@@ -186,8 +342,8 @@ static void keyboard_enter(void *data, struct wl_keyboard *keyboard,
(void)data;
(void)keyboard;
(void)serial;
- (void)surface;
(void)keys;
+ global.active_surface = surface;
}
static void keyboard_leave(void *data, struct wl_keyboard *keyboard,
@@ -206,6 +362,7 @@ static void keyboard_key(void *data, struct wl_keyboard *keyboard,
(void)serial;
(void)keyboard;
(void)time;
+ if (wl->surface != global.active_surface) return;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
stl_window_send_key_event(&wl->w, STELA_BUTTON_PRESSED, key);
} else if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
@@ -287,167 +444,7 @@ static const struct wl_seat_listener seat_listener = {
.name = seat_name
};
-static void handle_output_geometry(void *data, struct wl_output *output,
- s32 x, s32 y, s32 width_mm, s32 height_mm, s32 subpixel,
- const char *make, const char *model, s32 transform)
-{
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
- (void)output;
- (void)x;
- (void)y;
- (void)width_mm;
- (void)height_mm;
- (void)subpixel;
- (void)make;
- (void)model;
- switch (transform) {
- case WL_OUTPUT_TRANSFORM_90:
- case WL_OUTPUT_TRANSFORM_270:
- monitor->m.vertical = true;
- break;
- case WL_OUTPUT_TRANSFORM_NORMAL:
- case WL_OUTPUT_TRANSFORM_180:
- default:
- monitor->m.vertical = false;
- break;
- }
-}
-
-static void handle_output_mode(void *data, struct wl_output *output,
- u32 flags, s32 width, s32 height, s32 refresh)
-{
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
- (void)output;
- (void)flags;
- (void)refresh;
- if (monitor->m.vertical) {
- monitor->m.width = height;
- monitor->m.height = width;
- } else {
- monitor->m.width = width;
- monitor->m.height = height;
- }
-}
-
-static void handle_output_done(void *data, struct wl_output *output)
-{
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
- (void)output;
- al_log_info("window_wayland", "Output discovered: %s (%ux%u) (vertical: %s).",
- monitor->m.name, monitor->m.width, monitor->m.height, AL_BOOLSTR(monitor->m.vertical));
- if (monitor->m.window->output_discovered_callback) {
- monitor->m.window->output_discovered_callback(monitor->m.window->userdata, (struct stl_monitor *)monitor);
- }
-}
-
-static void handle_output_scale(void *data, struct wl_output *output, s32 factor)
-{
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
- (void)output;
- monitor->m.scale = factor;
-}
-
-static void handle_output_description(void *data, struct wl_output *output, const char *description)
-{
- (void)data;
- (void)output;
- (void)description;
-}
-
-static void handle_output_name(void *data, struct wl_output *output, const char *name)
-{
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
- (void)output;
- size_t len = strlen(name) + 1;
- al_memcpy(monitor->m.name, name, AL_MIN(len, STELA_MAX_MONITOR_NAME));
-}
-
-static const struct wl_output_listener output_listener = {
- .geometry = handle_output_geometry,
- .mode = handle_output_mode,
- .done = handle_output_done,
- .scale = handle_output_scale,
- .description = handle_output_description,
- .name = handle_output_name
-};
-
-/*
-static void handle_xdg_output_logical_position(void *data, struct zxdg_output_v1 *output, s32 x, s32 y)
-{
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)data;
- (void)output;
- monitor->m.x = x;
- monitor->m.y = y;
-}
-
-static void handle_xdg_output_logical_size(void *data, struct zxdg_output_v1 *output, s32 width, s32 height)
-{
- (void)data;
- (void)output;
- (void)width;
- (void)height;
-}
-
-static void handle_xdg_output_done(void *data, struct zxdg_output_v1 *output)
-{
- (void)data;
- (void)output;
-}
-
-static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, const char *name)
-{
- (void)data;
- (void)output;
- (void)name;
-}
-
-static void handle_xdg_output_description(void *data, struct zxdg_output_v1 *output, const char *description)
-{
- (void)data;
- (void)output;
- (void)description;
-}
-
-static const struct zxdg_output_v1_listener xdg_output_listener = {
- .logical_position = handle_xdg_output_logical_position,
- .logical_size = handle_xdg_output_logical_size,
- .done = handle_xdg_output_done,
- .name = handle_xdg_output_name,
- .description = handle_xdg_output_description
-};
-
-static void handle_toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager,
- struct zwlr_foreign_toplevel_handle_v1 *toplevel)
-{
- (void)data;
- (void)manager;
- (void)toplevel;
-}
-
-static void handle_finished(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager)
-{
- (void)data;
- (void)manager;
-}
-
-static const struct zwlr_foreign_toplevel_manager_v1_listener toplevel_manager_listener = {
- .toplevel = handle_toplevel,
- .finished = handle_finished
-};
-*/
-
-static void presentation_set_clock_id(void *data, struct wp_presentation *presentation, u32 clock_id)
-{
- struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
- al_assert(clock_id == CLOCK_MONOTONIC);
- wl->presentation = presentation;
-}
-
-static const struct wp_presentation_listener presentation_listener = {
- .clock_id = presentation_set_clock_id
-};
-
-static void global_add(void *data, struct wl_registry *registry, u32 name,
+static void context_global_add(void *data, struct wl_registry *registry, u32 name,
const char *interface, u32 version)
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
@@ -456,19 +453,6 @@ static void global_add(void *data, struct wl_registry *registry, u32 name,
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
wl->seat = wl_registry_bind(registry, name, &wl_seat_interface, AL_MIN(8u, version));
wl_seat_add_listener(wl->seat, &seat_listener, wl);
- } else if (strcmp(interface, wl_output_interface.name) == 0) {
- struct stl_monitor_wayland *monitor = al_alloc_object(struct stl_monitor_wayland);
- monitor->m.window = (struct stl_window *)wl;
- al_array_push(wl->w.monitors, (struct stl_monitor *)monitor);
- monitor->output = wl_registry_bind(registry, name, &wl_output_interface, AL_MIN(4u, version));
- wl_output_add_listener(monitor->output, &output_listener, monitor);
- // monitor->xdg_output = zxdg_output_manager_v1_get_xdg_output(wl->zxdg_output_manager, monitor->output);
- // zxdg_output_v1_add_listener(monitor->xdg_output, &xdg_output_listener, monitor);
- //} else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
- // wl->zxdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, AL_MIN(3u, version));
- //} else if (strcmp(interface, zwlr_foreign_toplevel_manager_v1_interface.name) == 0) {
- // wl->wlr_toplevel_manager = wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, AL_MIN(3u, version));
- // zwlr_foreign_toplevel_manager_v1_add_listener(wl->wlr_toplevel_manager, &toplevel_manager_listener, wl);
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
wl->xdg_wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, AL_MIN(2u, version));
xdg_wm_base_add_listener(wl->xdg_wm_base, &xdg_wm_base_listener, wl);
@@ -478,22 +462,19 @@ static void global_add(void *data, struct wl_registry *registry, u32 name,
wl->cursor_shape = wl_registry_bind(registry, name, &wp_cursor_shape_manager_v1_interface, AL_MIN(1u, version));
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
wl->layer_shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, AL_MIN(4u, version));
- } else if (strcmp(interface, wp_presentation_interface.name) == 0) {
- wl->presentation = wl_registry_bind(registry, name, &wp_presentation_interface, AL_MIN(1u, version));
- wp_presentation_add_listener(wl->presentation, &presentation_listener, wl);
}
}
-static void global_remove(void *data, struct wl_registry *registry, u32 name)
+static void context_global_remove(void *data, struct wl_registry *registry, u32 name)
{
(void)data;
(void)registry;
(void)name;
}
-static const struct wl_registry_listener registry_listener = {
- .global = global_add,
- .global_remove = global_remove
+static const struct wl_registry_listener context_registry_listener = {
+ .global = context_global_add,
+ .global_remove = context_global_remove
};
static void handle_surface_enter(void *data, struct wl_surface *surface, struct wl_output *output)
@@ -632,18 +613,10 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
#if defined STELA_API_OPENGL
static bool wl_egl_init(struct stl_window_wayland *wl)
{
- if (!stl_maybe_load_egl(&wl->egl)) return false;
-
wl->egl_window = wl_egl_window_create(wl->surface, wl->w.width, wl->w.height);
- wl->egl.display = eglGetDisplay((EGLNativeDisplayType)wl->display);
- if (!wl->egl.display) {
- al_log_error("window_wayland", "Failed to get wayland-native EGL display.");
- return false;
- }
-
EGLConfig config;
- if (!stl_init_egl(&wl->egl, 0, &config)) {
+ if (!stl_init_egl_context(&wl->egl, &global.egl, 0, &config)) {
return false;
}
@@ -662,11 +635,7 @@ static bool wl_egl_init(struct stl_window_wayland *wl)
static bool create_context_internal(struct stl_window_wayland *wl)
{
- wl->display = wl_display_connect(NULL);
- if (!wl->display) {
- al_log_error("window_wayland", "Failed to connect to the display.");
- return false;
- }
+ wl->display = global.display;
wl->fds[0].fd = wl_display_get_fd(wl->display);
wl->fds[0].events = POLLIN;
#if defined STELA_POLL_INLINE && defined STELA_PAUSE
@@ -674,7 +643,7 @@ static bool create_context_internal(struct stl_window_wayland *wl)
wl->fds[1].events = POLLIN;
#endif
wl->registry = wl_display_get_registry(wl->display);
- wl_registry_add_listener(wl->registry, &registry_listener, wl);
+ wl_registry_add_listener(wl->registry, &context_registry_listener, wl);
wl_display_roundtrip(wl->display);
wl_display_roundtrip(wl->display);
return true;
@@ -683,7 +652,7 @@ static bool create_context_internal(struct stl_window_wayland *wl)
static bool window_wayland_create_context(struct stl_window *window, s32 flags)
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)window;
- wl->flags = flags;
+ (void)flags;
if (!create_context_internal(wl)) {
wl->w.free((struct stl_window **)&wl);
return false;
@@ -691,39 +660,40 @@ static bool window_wayland_create_context(struct stl_window *window, s32 flags)
return true;
}
-static struct stl_monitor_wayland *monitor_from_name(struct stl_window_wayland *wl, const char *name)
+static struct stl_monitor_wayland *monitor_from_name(const char *name)
{
if (name) {
- for (u32 i = 0; i < wl->w.monitors.size; i++) {
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)al_array_at(wl->w.monitors, i);
+ for (u32 i = 0; i < global.monitors.size; i++) {
+ struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)al_array_at(global.monitors, i);
if (strcmp(monitor->m.name, name) == 0) return monitor;
}
}
- return (struct stl_monitor_wayland *)al_array_at(wl->w.monitors, 0);
+ return (struct stl_monitor_wayland *)al_array_at(global.monitors, 0);
}
-//static const struct wl_callback_listener frame_listener;
-
static bool window_wayland_create_window(struct stl_window *window, s32 width, s32 height,
const char *monitor, const char *name, s32 flags)
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)window;
- wl->flags = flags;
if (!create_context_internal(wl)) goto err;
- wl->monitor = monitor_from_name(wl, monitor);
- wl->w.scale = wl->monitor ? wl->monitor->m.scale : 1;
- wl->w.width = width * wl->w.scale;
- wl->w.height = height * wl->w.scale;
+ wl->monitor = monitor_from_name(monitor);
+ if (!wl->monitor) goto err;
+ wl->w.width = width;
+ wl->w.height = height;
wl->pending = true;
wl->surface = wl_compositor_create_surface(wl->compositor);
if (!wl->surface) goto err;
wl_surface_add_listener(wl->surface, &surface_listener, wl);
- wl_surface_set_buffer_scale(wl->surface, wl->w.scale);
if (!(flags & STELA_WINDOW_WALLPAPER)) {
+ wl->w.scale = wl->monitor->m.scale;
+ wl_surface_set_buffer_scale(wl->surface, wl->w.scale);
+ wl->w.width *= wl->w.scale;
+ wl->w.height *= wl->w.scale;
+
wl->xdg_surface = xdg_wm_base_get_xdg_surface(wl->xdg_wm_base, wl->surface);
if (!wl->xdg_surface) goto err;
xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, wl);
@@ -741,13 +711,12 @@ static bool window_wayland_create_window(struct stl_window *window, s32 width, s
wl->zxdg_decoration_manager, wl->xdg_toplevel);
zxdg_toplevel_decoration_v1_set_mode(wl->zxdg_toplevel_decoration, decor);
} else {
- u32 surface = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
- //u32 surface = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
+ u32 surface = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
+ //u32 surface = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
u32 anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
| ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
- //u32 anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
wl->layer_surface = zwlr_layer_shell_v1_get_layer_surface(wl->layer_shell,
wl->surface, wl->monitor->output, surface, name);
if (!wl->layer_surface) goto err;
@@ -768,14 +737,10 @@ static bool window_wayland_create_window(struct stl_window *window, s32 width, s
#if defined STELA_API_OPENGL
stl_egl_make_current(&wl->egl);
- stl_egl_swap_interval(&wl->egl, (wl->flags & STELA_WINDOW_VSYNC) ? 1 : 0);
+ stl_egl_swap_interval(&wl->egl, (flags & STELA_WINDOW_VSYNC) ? 1 : 0);
stl_egl_release_current(&wl->egl);
#endif
- //wl->frame_done = 0;
- //wl->frame_callback = wl_surface_frame(wl->surface);
- //wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
-
wl->pointer_x = 0.0;
wl->pointer_y = 0.0;
wl->scroll_x = 0.0;
@@ -865,9 +830,9 @@ static bool window_wayland_should_refresh(struct stl_window *window)
static void destroy_surface_internal(struct stl_window_wayland *wl)
{
if (wl->xdg_surface) {
- xdg_surface_destroy(wl->xdg_surface);
if (wl->zxdg_toplevel_decoration) zxdg_toplevel_decoration_v1_destroy(wl->zxdg_toplevel_decoration);
if (wl->xdg_toplevel) xdg_toplevel_destroy(wl->xdg_toplevel);
+ xdg_surface_destroy(wl->xdg_surface);
} else if (wl->layer_surface) {
zwlr_layer_surface_v1_destroy(wl->layer_surface);
}
@@ -890,25 +855,16 @@ void window_wayland_free(struct stl_window **window)
if (wl->cursor_shape) wp_cursor_shape_manager_v1_destroy(wl->cursor_shape);
if (wl->cursor_shape_device) wp_cursor_shape_device_v1_destroy(wl->cursor_shape_device);
if (wl->keyboard) wl_keyboard_destroy(wl->keyboard);
- if (wl->compositor) wl_compositor_destroy(wl->compositor);
- for (u32 i = 0; i < wl->w.monitors.size; i++) {
- struct stl_monitor_wayland *monitor = (struct stl_monitor_wayland *)al_array_at(wl->w.monitors, i);
- if (monitor->output) wl_output_destroy(monitor->output);
- al_free(monitor);
- }
- al_array_free(wl->w.monitors);
- if (wl->xdg_wm_base) xdg_wm_base_destroy(wl->xdg_wm_base);
+ destroy_surface_internal(wl);
if (wl->zxdg_decoration_manager) zxdg_decoration_manager_v1_destroy(wl->zxdg_decoration_manager);
+ if (wl->xdg_wm_base) xdg_wm_base_destroy(wl->xdg_wm_base);
if (wl->layer_shell) zwlr_layer_shell_v1_destroy(wl->layer_shell);
- if (wl->presentation) wp_presentation_destroy(wl->presentation);
- destroy_surface_internal(wl);
+ if (wl->compositor) wl_compositor_destroy(wl->compositor);
#if defined STELA_API_OPENGL
if (stl_egl_is_ready(&wl->egl)) {
stl_egl_destroy_context(&wl->egl);
- stl_egl_terminate(&wl->egl);
}
#endif
- wl_display_disconnect(wl->display);
#if defined STELA_EVENT_BUFFER
al_free(wl->w.data);
#endif
@@ -916,64 +872,6 @@ void window_wayland_free(struct stl_window **window)
*window = NULL;
}
-/*
-static void feedback_sync_output(void *data, struct wp_presentation_feedback *feedback,
- struct wl_output *output)
-{
- (void)data;
- (void)feedback;
- (void)output;
-}
-
-static void feedback_presented(void *data, struct wp_presentation_feedback *feedback,
- u32 tv_sec_hi, u32 tv_sec_lo, u32 tv_nsec, u32 refresh_nsec,
- u32 seq_hi, u32 seq_lo, u32 flags)
-{
- struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
- (void)refresh_nsec;
- (void)seq_hi;
- (void)seq_lo;
- (void)flags;
- wp_presentation_feedback_destroy(feedback);
- u64 sec = (u64)tv_sec_lo + ((u64)tv_sec_hi << 32);
- u64 nsec = sec * 1000000000 + (u64)tv_nsec;
- wl->presentation_time = ((f64)(nsec * 1e-9));
-}
-
-static void feedback_discarded(void *data, struct wp_presentation_feedback *feedback)
-{
- struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
- wp_presentation_feedback_destroy(feedback);
- wl->presentation_time = 0.0;
-}
-
-static const struct wp_presentation_feedback_listener feedback_listener = {
- .sync_output = feedback_sync_output,
- .presented = feedback_presented,
- .discarded = feedback_discarded
-};
-
-static void frame_callback(void *data, struct wl_callback *callback, u32 time)
-{
- struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
- (void)time;
-
- if (callback) wl_callback_destroy(callback);
-
- wl->frame_callback = wl_surface_frame(wl->surface);
- wl_callback_add_listener(wl->frame_callback, &frame_listener, wl);
-
- wl->frame_done = 1;
-
- struct wp_presentation_feedback *feedback = wp_presentation_feedback(wl->presentation, wl->surface);
- wp_presentation_feedback_add_listener(feedback, &feedback_listener, wl);
-}
-
-static const struct wl_callback_listener frame_listener = {
- .done = frame_callback
-};
-*/
-
#if defined STELA_API_OPENGL
static bool window_wayland_gl_loader_load(void *data)
{
@@ -1000,22 +898,13 @@ static void window_wayland_gl_release_current(void *data)
static void window_wayland_gl_swap_buffers(void *data)
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)data;
- //wl->frame_done = 0;
stl_egl_swap_buffers(&wl->egl);
- /*
- // This is not correct and cannot be expected to work anything like vsync or
- // it will introduce massive input lag.
- while (!wl->frame_done) {
-#if defined STELA_POLL_INLINE
- wl->w.poll(&wl->w, true);
-#endif
- }
- */
}
#endif
-struct stl_window *stl_window_wayland_create(void)
+struct stl_window *stl_window_create(void)
{
+ al_log_info("stela", "Creating Wayland (EGL) window.");
struct stl_window_wayland *wl = al_alloc_object(struct stl_window_wayland);
#if defined STELA_EVENT_BUFFER
wl->w.data = al_malloc(STELA_EVENTS_SIZE);
@@ -1025,7 +914,6 @@ struct stl_window *stl_window_wayland_create(void)
wl->w.pending_refresh = true;
#endif
wl->w.fullscreen = false;
- al_array_init(wl->w.monitors);
wl->w.create_context = window_wayland_create_context;
wl->w.create_window = window_wayland_create_window;
wl->w.resize = window_wayland_resize;
diff --git a/src/window_wayland.h b/src/window_wayland.h
index 07a12b6..157705e 100644
--- a/src/window_wayland.h
+++ b/src/window_wayland.h
@@ -10,14 +10,22 @@
#include <xdg-shell-client-protocol.h>
#include <xdg-decoration-unstable-v1-client-protocol.h>
#include <cursor-shape-v1-client-protocol.h>
-//#include <xdg-output-unstable-v1-client-protocol.h>
-//#include <wlr-foreign-toplevel-management-unstable-v1-client-protocol.h>
#include <wlr-layer-shell-unstable-v1-client-protocol.h>
-#include <presentation-time-client-protocol.h>
+//#include <presentation-time-client-protocol.h>
#include "window.h"
#include "egl_common.h"
+struct stl_wayland_global {
+ struct wl_display *display;
+ struct stl_egl_global egl;
+ struct wl_registry *registry;
+ struct wl_surface *active_surface;
+ array(struct stl_monitor *) monitors;
+ void (*output_discovered)(void *, struct stl_monitor *);
+ void *userdata;
+};
+
struct stl_monitor_wayland {
struct stl_monitor m;
struct wl_output *output;
@@ -26,7 +34,6 @@ struct stl_monitor_wayland {
struct stl_window_wayland {
struct stl_window w;
- s32 flags;
struct wl_display *display;
struct wl_registry *registry;
struct wl_seat *seat;
@@ -34,8 +41,6 @@ struct stl_window_wayland {
struct wl_keyboard *keyboard;
struct wl_compositor *compositor;
struct wl_surface *surface;
- //struct zxdg_output_manager_v1 *zxdg_output_manager;
- //struct zwlr_foreign_toplevel_manager_v1 *wlr_toplevel_manager;
struct xdg_wm_base *xdg_wm_base;
bool pending;
struct xdg_surface *xdg_surface;
@@ -47,10 +52,6 @@ struct stl_window_wayland {
struct zwlr_layer_shell_v1 *layer_shell;
struct stl_monitor_wayland *monitor;
struct zwlr_layer_surface_v1 *layer_surface;
- struct wl_callback *frame_callback;
- s32 frame_done;
- struct wp_presentation *presentation;
- f64 presentation_time;
struct stl_egl egl;
struct wl_egl_window *egl_window;
#if defined STELA_POLL_INLINE && defined STELA_PAUSE
@@ -65,5 +66,3 @@ struct stl_window_wayland {
f64 scroll_x;
f64 scroll_y;
};
-
-struct stl_window *stl_window_wayland_create(void);
diff --git a/src/window_x11.c b/src/window_x11.c
index eb64982..53cf0b5 100644
--- a/src/window_x11.c
+++ b/src/window_x11.c
@@ -1,6 +1,7 @@
#include <al/log.h>
#include "window_x11.h"
+#include "common.h"
#include "poll_common.h"
static Atom ATOM_WM_DELETE_WINDOW;
@@ -11,17 +12,40 @@ static Atom ATOM_WM_DELETE_WINDOW;
#define _NET_WM_STATE_ADD 1
#define _NET_WM_STATE_TOGGLE 2
-static bool x11_egl_init(struct stl_window_x11 *xw)
+static struct stl_x11_global global;
+
+void stl_set_output_discovered_callback(void (*output_discovered)(void *, struct stl_monitor *), void *userdata)
{
- if (!stl_maybe_load_egl(&xw->egl)) return false;
+ (void)output_discovered;
+ (void)userdata;
+}
- xw->egl.display = eglGetDisplay((EGLNativeDisplayType)xw->x11_d);
- if (!xw->egl.display) {
- al_log_error("window_x11", "Failed to get x11 EGL display.");
+bool stl_global_init(void)
+{
+ global.x11_d = XOpenDisplay(NULL);
+ if (!global.x11_d) {
+ al_log_error("x11", "Couldn't open display.");
+ return false;
}
+#if defined STELA_API_OPENGL
+ if (!stl_maybe_load_egl()) return false;
+ global.egl.display = eglGetDisplay((EGLNativeDisplayType)global.x11_d);
+ if (!global.egl.display) {
+ al_log_error("x11", "Failed to get x11 EGL display.");
+ }
+ if (!stl_load_egl(&global.egl)) return false;
+#endif
+ return true;
+}
+
+void stl_global_close(void)
+{
+}
+static bool x11_egl_init(struct stl_window_x11 *xw)
+{
EGLConfig config;
- if (!stl_init_egl(&xw->egl, 0, &config)) {
+ if (!stl_init_egl_context(&xw->egl, &global.egl, 0, &config)) {
return false;
}
@@ -45,11 +69,7 @@ static bool window_x11_create_window(struct stl_window *window, s32 width, s32 h
struct stl_window_x11 *xw = (struct stl_window_x11 *)window;
(void)monitor;
- xw->x11_d = XOpenDisplay(NULL);
- if (!xw->x11_d) {
- al_log_error("window_x11", "Couldn't open display.");
- return false;
- }
+ xw->x11_d = global.x11_d;
s32 screen = XDefaultScreen(xw->x11_d);
Window root = RootWindow(xw->x11_d, screen);
@@ -246,7 +266,6 @@ static void window_x11_free(struct stl_window **window)
#if defined STELA_EVENT_BUFFER
al_free(xw->w.data);
#endif
- al_array_free(xw->w.monitors);
al_free(xw);
*window = NULL;
}
@@ -297,8 +316,9 @@ static void window_x11_gl_swap_buffers(void *data)
}
#endif
-struct stl_window *stl_window_x11_create(void)
+struct stl_window *stl_window_create(void)
{
+ al_log_info("stela", "Creating X11 (EGL) window.");
struct stl_window_x11 *xw = al_alloc_object(struct stl_window_x11);
#if defined STELA_EVENT_BUFFER
xw->w.data = al_malloc(STELA_EVENTS_SIZE);
@@ -308,7 +328,6 @@ struct stl_window *stl_window_x11_create(void)
xw->w.pending_refresh = true;
#endif
xw->w.fullscreen = false;
- al_array_init(xw->w.monitors);
xw->w.create_context = NULL;
xw->w.create_window = window_x11_create_window;
xw->w.resize = window_x11_resize;
diff --git a/src/window_x11.h b/src/window_x11.h
index c365d91..8b69e7f 100644
--- a/src/window_x11.h
+++ b/src/window_x11.h
@@ -8,6 +8,11 @@
#include "window.h"
#include "egl_common.h"
+struct stl_x11_global {
+ Display *x11_d;
+ struct stl_egl_global egl;
+};
+
struct stl_window_x11 {
struct stl_window w;
Display *x11_d;
@@ -19,5 +24,3 @@ struct stl_window_x11 {
struct aki_pollfd fds[1];
#endif
};
-
-struct stl_window *stl_window_x11_create(void);
diff --git a/subprojects/glfw3.wrap b/subprojects/glfw3.wrap
index c1166ba..684a293 100644
--- a/subprojects/glfw3.wrap
+++ b/subprojects/glfw3.wrap
@@ -1,5 +1,5 @@
[wrap-git]
url = https://github.com/glfw/glfw.git
-revision = 228e58262e18f2ee61799bd86d0be718b1e31f9f
+revision = b35641f4a3c62aa86a0b3c983d163bc0fe36026d
depth = 1
method = cmake