summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-02-19 17:36:17 -0500
committerAndrew Opalach <andrew@akon.city> 2025-02-19 17:36:17 -0500
commitc0cd683e98f357d4b81cfd44444dbc909dcb2386 (patch)
tree4923cc407e7ffecaecc7e3e1ce94de6662becac8 /src
parentdda9ba19bb94947cf7d2f176f0d6760078598b69 (diff)
downloadstela-c0cd683e98f357d4b81cfd44444dbc909dcb2386.tar.gz
stela-c0cd683e98f357d4b81cfd44444dbc909dcb2386.tar.bz2
stela-c0cd683e98f357d4b81cfd44444dbc909dcb2386.zip
Fix EGL Wayland resize issue, support DX11 in GLFW
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src')
-rw-r--r--src/egl_common.c17
-rw-r--r--src/window.h4
-rw-r--r--src/window_glfw.c46
-rw-r--r--src/window_glfw.h14
-rw-r--r--src/window_wayland.c6
5 files changed, 72 insertions, 15 deletions
diff --git a/src/egl_common.c b/src/egl_common.c
index 7bbcba9..b2f0688 100644
--- a/src/egl_common.c
+++ b/src/egl_common.c
@@ -168,6 +168,7 @@ bool stl_init_egl_context(struct stl_egl *egl, struct stl_egl_global *global, EG
void stl_egl_make_current(struct stl_egl *egl)
{
if (egl->context != egl->current) {
+ al_assert(egl->current == EGL_NO_CONTEXT); // 1 context limit (for now).
eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context);
egl->current = egl->context;
}
@@ -176,8 +177,20 @@ void stl_egl_make_current(struct stl_egl *egl)
void stl_egl_release_current(struct stl_egl *egl)
{
al_assert(egl->context == egl->current);
- eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- egl->current = EGL_NO_CONTEXT;
+ // https://gitlab.freedesktop.org/mesa/mesa/-/issues/6547
+ // libplacebo calls release_current() after swapping buffers. That locks in the
+ // current backbuffer size. So, if all that happens for the next frame is:
+ // 1. wl_egl_window_resize()
+ // 2. resize libplacebo swapchain
+ // 3. start frame
+ // 4. submit frame
+ // 5. swap buffers
+ // The frame that is presented will still have the dimensions of the previous backbuffer.
+ // We only support 1 context at a time, so this shouldn't be an issue.
+#if 0
+ eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ egl->current = EGL_NO_CONTEXT;
+#endif
}
void stl_egl_swap_interval(struct stl_egl *egl, EGLint interval)
diff --git a/src/window.h b/src/window.h
index 11ba00f..7c71056 100644
--- a/src/window.h
+++ b/src/window.h
@@ -20,6 +20,8 @@
#if defined STELA_API_VULKAN
#include <vulkan/vulkan.h>
+#elif defined STELA_API_DX11
+#include <nnwt/windows.h>
#elif defined STELA_API_OPENGL && defined STELA_USE_EGL
#include "egl_common.h"
#endif
@@ -82,6 +84,8 @@ struct stl_window {
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL (*get_vk_proc_address)(VkInstance, const char *);
VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *);
const char *const *(*vk_get_extensions)(u32 *);
+#elif defined STELA_API_DX11
+ HWND win32_window;
#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
EGLDisplay egl_display;
diff --git a/src/window_glfw.c b/src/window_glfw.c
index fc7b020..836e7c8 100644
--- a/src/window_glfw.c
+++ b/src/window_glfw.c
@@ -45,7 +45,6 @@ bool stl_global_init(bool skip_graphics)
return false;
}
global.master_window = NULL;
- al_log_info("glfw", "Successfully initialized GLFW.");
return true;
}
@@ -85,12 +84,28 @@ static void mouse_button_callback(GLFWwindow *window, s32 button, s32 action, s3
{
struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
(void)mods;
- if (button == GLFW_MOUSE_BUTTON_1) {
+ switch (button) {
+ case GLFW_MOUSE_BUTTON_1:
if (action == GLFW_PRESS) {
stl_window_send_mouse_button_event(&glfw->w, STELA_BUTTON_PRESSED, STELA_MOUSE1);
} else if (action == GLFW_RELEASE) {
stl_window_send_mouse_button_event(&glfw->w, STELA_BUTTON_RELEASED, STELA_MOUSE1);
}
+ break;
+ case GLFW_MOUSE_BUTTON_2:
+ if (action == GLFW_PRESS) {
+ stl_window_send_mouse_button_event(&glfw->w, STELA_BUTTON_PRESSED, STELA_MOUSE2);
+ } else if (action == GLFW_RELEASE) {
+ stl_window_send_mouse_button_event(&glfw->w, STELA_BUTTON_RELEASED, STELA_MOUSE2);
+ }
+ break;
+ case GLFW_MOUSE_BUTTON_3:
+ if (action == GLFW_PRESS) {
+ stl_window_send_mouse_button_event(&glfw->w, STELA_BUTTON_PRESSED, STELA_MOUSE3);
+ } else if (action == GLFW_RELEASE) {
+ stl_window_send_mouse_button_event(&glfw->w, STELA_BUTTON_RELEASED, STELA_MOUSE3);
+ }
+ break;
}
}
@@ -104,7 +119,10 @@ static void scroll_callback(GLFWwindow *window, f64 xoffset, f64 yoffset)
static void resize_callback(GLFWwindow *window, s32 event_width, s32 event_height)
{
struct stl_window_glfw *glfw = glfwGetWindowUserPointer(window);
- al_assert(event_width > 0 && event_height > 0);
+ if (event_width <= 0 || event_height <= 0) {
+ // This happens on Windows when minimizing.
+ return;
+ }
u32 width = (u32)event_width;
u32 height = (u32)event_height;
@@ -138,10 +156,18 @@ static bool window_glfw_create_window(struct stl_window *window, u32 width, u32
struct stl_window_glfw *glfw = (struct stl_window_glfw *)window;
(void)monitor;
+#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4)
glfwWindowHintString(GLFW_WAYLAND_APP_ID, name);
+#endif
glfwWindowHintString(GLFW_X11_CLASS_NAME, name);
-#if defined STELA_API_VULKAN || defined STELA_API_DX11
+#if defined STELA_API_VULKAN
+ if (!glfwVulkanSupported()) {
+ al_log_error("window_glfw", "Vulkan not supported.");
+ return false;
+ }
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+#elif defined STELA_API_DX11
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
#elif defined STELA_API_OPENGL
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
@@ -180,7 +206,12 @@ static bool window_glfw_create_window(struct stl_window *window, u32 width, u32
global.master_window = glfw->window;
}
-#ifdef STELA_API_OPENGL
+#if defined STELA_API_VULKAN
+ (void)flags;
+#elif defined STELA_API_DX11
+ (void)flags;
+ glfw->w.win32_window = glfwGetWin32Window(glfw->window);
+#elif defined STELA_API_OPENGL
#ifdef STELA_USE_EGL
glfw->w.egl_display = glfwGetEGLDisplay();
glfw->w.egl_context = glfwGetEGLContext(glfw->window);
@@ -189,7 +220,6 @@ static bool window_glfw_create_window(struct stl_window *window, u32 width, u32
glfwSwapInterval((flags & STELA_WINDOW_VSYNC) ? 1 : 0);
glfwMakeContextCurrent(NULL);
#else
- (void)flags;
#endif
s32 buffer_width, buffer_height;
@@ -237,11 +267,13 @@ static void window_glfw_resize(struct stl_window *window, u32 width, u32 height)
// https://stackoverflow.com/a/31526753
static GLFWmonitor *get_current_monitor(GLFWwindow *window, s32 wx, s32 wy)
{
+#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4)
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) {
// Calculating the current monitor doesn't work on Wayland
// because we can't know the position of the window.
return glfwGetPrimaryMonitor();
}
+#endif
s32 monitor_count;
GLFWmonitor **monitors = glfwGetMonitors(&monitor_count);
@@ -283,9 +315,11 @@ static void window_glfw_toggle_fullscreen(struct stl_window *window)
{
struct stl_window_glfw *glfw = (struct stl_window_glfw *)window;
if (!glfw->w.fullscreen) {
+#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR >= 4)
if (glfwGetPlatform() != GLFW_PLATFORM_WAYLAND) {
glfwGetWindowPos(glfw->window, &glfw->prev.x, &glfw->prev.y);
}
+#endif
GLFWmonitor *monitor = get_current_monitor(glfw->window, glfw->prev.x, glfw->prev.y);
if (!monitor) return;
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
diff --git a/src/window_glfw.h b/src/window_glfw.h
index f834f29..2cde53c 100644
--- a/src/window_glfw.h
+++ b/src/window_glfw.h
@@ -6,15 +6,19 @@
#define GLFW_INCLUDE_NONE
#endif
#include <GLFW/glfw3.h>
-#ifdef STELA_USE_EGL
-#define GLFW_EXPOSE_NATIVE_EGL
+
+#include "window.h"
+
+#if defined STELA_API_DX11
#define GLFW_NATIVE_INCLUDE_NONE
-#include "egl_common.h"
+#define GLFW_EXPOSE_NATIVE_WIN32
+#include <GLFW/glfw3native.h>
+#elif defined STELA_USE_EGL
+#define GLFW_NATIVE_INCLUDE_NONE
+#define GLFW_EXPOSE_NATIVE_EGL
#include <GLFW/glfw3native.h>
#endif
-#include "window.h"
-
struct stl_glfw_global {
GLFWwindow *master_window;
};
diff --git a/src/window_wayland.c b/src/window_wayland.c
index 31d1e13..6935f0e 100644
--- a/src/window_wayland.c
+++ b/src/window_wayland.c
@@ -738,6 +738,7 @@ static bool create_toplevel(struct stl_window_wayland *wl, s32 scale, const char
{
wl->w.scale = scale;
wl_surface_set_buffer_scale(wl->surface, scale);
+ u32 geom_width = wl->w.width, geom_height = wl->w.height;
wl->w.width *= scale;
wl->w.height *= scale;
wl->pending = true;
@@ -757,7 +758,7 @@ static bool create_toplevel(struct stl_window_wayland *wl, s32 scale, const char
xdg_toplevel_set_title(wl->xdg_toplevel, name);
xdg_toplevel_set_app_id(wl->xdg_toplevel, name);
xdg_toplevel_set_min_size(wl->xdg_toplevel, STELA_MIN_WIDTH, STELA_MIN_HEIGHT);
- //xdg_surface_set_window_geometry(wl->xdg_surface, 0, 0, wl->w.width, wl->w.height);
+ xdg_surface_set_window_geometry(wl->xdg_surface, 0, 0, geom_width, geom_height);
u32 decor = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
wl->zxdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
@@ -853,7 +854,8 @@ static void window_wayland_resize_internal(struct stl_window *window, u32 width,
{
struct stl_window_wayland *wl = (struct stl_window_wayland *)window;
#ifdef STELA_API_OPENGL
- //xdg_surface_set_window_geometry(wl->xdg_surface, 0, 0, width, height);
+ u32 scale = wl->w.scale;
+ xdg_surface_set_window_geometry(wl->xdg_surface, 0, 0, width / scale, height / scale);
if (stl_egl_is_ready(&wl->egl)) {
wl_egl_window_resize(wl->egl_window, width, height, 0, 0);
}