From 72e52678a96c8f9350a992a062afb1c11e685102 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Thu, 19 Sep 2024 15:06:37 -0400 Subject: Initial global context/multiple window support Signed-off-by: Andrew Opalach --- src/egl_common.c | 76 ++++---- src/egl_common.h | 12 +- src/gl_common.c | 5 +- src/gl_common.h | 5 +- src/poll_common.c | 2 + src/stela.c | 27 --- src/window.h | 7 +- src/window_glfw.c | 67 +++++-- src/window_glfw.h | 8 +- src/window_wayland.c | 498 ++++++++++++++++++++------------------------------- src/window_wayland.h | 23 ++- src/window_x11.c | 47 +++-- src/window_x11.h | 7 +- 13 files changed, 355 insertions(+), 429 deletions(-) delete mode 100644 src/stela.c (limited to 'src') 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 #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 #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 - -#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, ®istry_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, ®istry_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 #include #include -//#include -//#include #include -#include +//#include #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 #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); -- cgit v1.2.3-101-g0448