diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a00e67c..409876f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ option(LOVR_USE_OCULUS "Enable the LibOVR backend for the headset module (be sur option(LOVR_USE_VRAPI "Enable the VrApi backend for the headset module" OFF) option(LOVR_USE_PICO "Enable the Pico backend for the headset module" OFF) option(LOVR_USE_DESKTOP_HEADSET "Enable the keyboard/mouse backend for the headset module" ON) +option(LOVR_USE_LINUX_EGL "Use the EGL graphics extension on Linux" OFF) option(LOVR_SYSTEM_ENET "Use the system-provided enet" OFF) option(LOVR_SYSTEM_GLFW "Use the system-provided glfw" OFF) @@ -691,6 +692,12 @@ elseif(ANDROID) ) endif() elseif(UNIX) - target_sources(lovr PRIVATE src/core/os_linux.c) + if(LOVR_USE_LINUX_EGL) + target_sources(lovr PRIVATE src/core/os_linux.c) + target_compile_definitions(lovr PRIVATE -DLOVR_LINUX_EGL) + else() + target_sources(lovr PRIVATE src/core/os_linux.c) + target_compile_definitions(lovr PRIVATE -DLOVR_LINUX_X11) + endif() target_compile_definitions(lovr PRIVATE -DLOVR_GL) endif() diff --git a/src/api/l_math.c b/src/api/l_math.c index 2d706c45..1df84554 100644 --- a/src/api/l_math.c +++ b/src/api/l_math.c @@ -110,6 +110,13 @@ static int l_lovrMathNewCurve(lua_State* L) { i += 3 + components; lua_pop(L, 3); } + } else if (top == 1 && lua_type(L, 1) == LUA_TNUMBER) { + float point[4] = { 0 }; + int count = lua_tonumber(L, 1); + lovrAssert(count > 0, "Number of curve points must be positive"); + for (int i = 0; i < count; i++) { + lovrCurveAddPoint(curve, point, i); + } } else { int pointIndex = 0; for (int i = 1; i <= top;) { diff --git a/src/core/os_glfw.h b/src/core/os_glfw.h index b3be66a1..88109c80 100644 --- a/src/core/os_glfw.h +++ b/src/core/os_glfw.h @@ -2,12 +2,26 @@ #define GLFW_INCLUDE_NONE #include + #ifndef EMSCRIPTEN -#ifdef _WIN32 -#define GLFW_EXPOSE_NATIVE_WIN32 -#define GLFW_EXPOSE_NATIVE_WGL -#endif -#include +# ifdef _WIN32 +# define GLFW_EXPOSE_NATIVE_WIN32 +# define GLFW_EXPOSE_NATIVE_WGL +# endif +# ifdef _WIN32 +# define GLFW_EXPOSE_NATIVE_WIN32 +# define GLFW_EXPOSE_NATIVE_WGL +# endif +# ifdef LOVR_LINUX_EGL +# define EGL_NO_X11 +# include +# define GLFW_EXPOSE_NATIVE_EGL +# endif +# ifdef LOVR_LINUX_X11 +# define GLFW_EXPOSE_NATIVE_X11 +# define GLFW_EXPOSE_NATIVE_GLX +# endif +# include #endif static struct { @@ -204,12 +218,18 @@ bool lovrPlatformCreateWindow(const WindowFlags* flags) { return false; } + +#ifdef LOVR_LINUX_EGL + glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); +#endif glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, flags->debug); +#ifndef LOVR_LINUX_EGL glfwWindowHint(GLFW_CONTEXT_NO_ERROR, !flags->debug); +#endif glfwWindowHint(GLFW_SAMPLES, flags->msaa); glfwWindowHint(GLFW_RESIZABLE, flags->resizable); glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE); @@ -345,3 +365,56 @@ HGLRC lovrPlatformGetContext() { return glfwGetWGLContext(glfwState.window); } #endif + +#ifdef LOVR_LINUX_EGL +PFNEGLGETPROCADDRESSPROC lovrPlatformGetEGLProcAddr(void) +{ + return (PFNEGLGETPROCADDRESSPROC)glfwGetProcAddress; +} + +EGLDisplay lovrPlatformGetEGLDisplay(void) +{ + return glfwGetEGLDisplay(); +} + +EGLContext lovrPlatformGetEGLContext(void) +{ + return glfwGetEGLContext(glfwState.window); +} + +EGLConfig lovrPlatformGetEGLConfig(void) +{ + EGLDisplay dpy = lovrPlatformGetEGLDisplay(); + EGLContext ctx = lovrPlatformGetEGLContext(); + EGLint cfg_id = -1; + EGLint num_cfgs = -1; + EGLConfig cfg = NULL; + PFNEGLQUERYCONTEXTPROC eglQueryContext = (PFNEGLQUERYCONTEXTPROC)glfwGetProcAddress("eglQueryContext"); + PFNEGLCHOOSECONFIGPROC eglChooseConfig = (PFNEGLCHOOSECONFIGPROC)glfwGetProcAddress("eglChooseConfig"); + + eglQueryContext(dpy, ctx, EGL_CONFIG_ID, &cfg_id); + EGLint attrs [4] = { + EGL_CONFIG_ID, cfg_id, + EGL_NONE, EGL_NONE, + }; + eglChooseConfig(dpy, attrs, &cfg, 1, &num_cfgs); + return cfg; +} +#endif + +#ifdef LOVR_LINUX_X11 +Display* lovrPlatformGetX11Display(void) +{ + return glfwGetX11Display(); +} + +GLXDrawable lovrPlatformGetGLXDrawable(void) +{ + return glfwGetGLXWindow(glfwState.window); +} + +GLXContext lovrPlatformGetGLXContext(void) +{ + return glfwGetGLXContext(glfwState.window); +} +#endif diff --git a/src/modules/headset/headset_openxr.c b/src/modules/headset/headset_openxr.c index 9dda647b..85be85cf 100644 --- a/src/modules/headset/headset_openxr.c +++ b/src/modules/headset/headset_openxr.c @@ -24,6 +24,19 @@ #define XR_USE_GRAPHICS_API_OPENGL_ES #define GRAPHICS_EXTENSION "XR_KHR_opengl_es_enable" #endif +#if defined(LOVR_LINUX_X11) + #define XR_USE_PLATFORM_XLIB + typedef unsigned long XID; + typedef struct Display Display; + typedef XID GLXFBConfig; + typedef XID GLXDrawable; + typedef XID GLXContext; +#endif +#if defined(LOVR_LINUX_EGL) + #define XR_USE_PLATFORM_EGL + #define EGL_NO_X11 + #include +#endif #define XR_NO_PROTOTYPES #include #include @@ -46,6 +59,15 @@ struct ANativeActivity* lovrPlatformGetActivity(void); EGLDisplay lovrPlatformGetEGLDisplay(void); EGLContext lovrPlatformGetEGLContext(void); EGLConfig lovrPlatformGetEGLConfig(void); +#elif defined(LOVR_LINUX_X11) +Display* lovrPlatformGetX11Display(void); +GLXDrawable lovrPlatformGetGLXDrawable(void); +GLXContext lovrPlatformGetGLXContext(void); +#elif defined(LOVR_LINUX_EGL) +PFNEGLGETPROCADDRESSPROC lovrPlatformGetEGLProcAddr(void); +EGLDisplay lovrPlatformGetEGLDisplay(void); +EGLContext lovrPlatformGetEGLContext(void); +EGLConfig lovrPlatformGetEGLConfig(void); #endif #define XR_FOREACH(X)\ @@ -183,6 +205,10 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa) { enabledExtensionNames[enabledExtensionCount++] = XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME; #endif +#ifdef LOVR_LINUX_EGL + enabledExtensionNames[enabledExtensionCount++] = "XR_MNDX_egl_enable"; +#endif + enabledExtensionNames[enabledExtensionCount++] = GRAPHICS_EXTENSION; if (hasExtension(extensions, extensionCount, XR_EXT_HAND_TRACKING_EXTENSION_NAME)) { @@ -326,6 +352,25 @@ static bool openxr_init(float supersample, float offset, uint32_t msaa) { .config = lovrPlatformGetEGLConfig(), .context = lovrPlatformGetEGLContext() }; +#elif defined(LOVR_LINUX_X11) + XrGraphicsBindingOpenGLXlibKHR graphicsBinding = { + .type = XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, + .next = NULL, + .xDisplay = lovrPlatformGetX11Display(), + .visualid = 0, + .glxFBConfig = 0, + .glxDrawable = lovrPlatformGetGLXDrawable(), + .glxContext = lovrPlatformGetGLXContext(), + }; +#elif defined(LOVR_LINUX_EGL) + XrGraphicsBindingEGLMNDX graphicsBinding = { + .type = XR_TYPE_GRAPHICS_BINDING_EGL_MNDX, + .next = NULL, + .getProcAddress = lovrPlatformGetEGLProcAddr(), + .display = lovrPlatformGetEGLDisplay(), + .config = lovrPlatformGetEGLConfig(), + .context = lovrPlatformGetEGLContext(), + }; #else #error "Unsupported OpenXR platform/graphics combination" #endif