Refine OpenXR backend formatting
This commit is contained in:
3
AGENTS.md
Normal file
3
AGENTS.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Coding conventions:
|
||||||
|
- Use `clang-format` on all C and C++ sources before committing.
|
||||||
|
- In `CMakeLists.txt`, indent with four spaces. Tabs may be used for C++ files as per .clang-format.
|
||||||
@@ -28,27 +28,28 @@ pkg_check_modules(X11 REQUIRED x11)
|
|||||||
pkg_check_modules(wayland REQUIRED wayland-server wayland-protocols)
|
pkg_check_modules(wayland REQUIRED wayland-server wayland-protocols)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${wayland_INCLUDE_DIRS}
|
${wayland_INCLUDE_DIRS}
|
||||||
${X11_INCLUDE_DIRS}
|
${X11_INCLUDE_DIRS}
|
||||||
${GLM_INCLUDE_DIRS}
|
${GLM_INCLUDE_DIRS}
|
||||||
${Wlroots_INCLUDE_DIRS}
|
${Wlroots_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
src/wlr/backend.cpp
|
src/wlr/backend.cpp
|
||||||
src/wlr/output.cpp
|
src/wlr/output.cpp
|
||||||
|
src/wlr/openxr_gl.cpp
|
||||||
|
|
||||||
src/compositor.cpp
|
src/compositor.cpp
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
OpenGL::GL
|
OpenGL::GL
|
||||||
openxr_loader
|
openxr_loader
|
||||||
${wayland_LIBRARIES}
|
${wayland_LIBRARIES}
|
||||||
${X11_LIBRARIES}
|
${X11_LIBRARIES}
|
||||||
${GLM_LIBRARIES}
|
${GLM_LIBRARIES}
|
||||||
${Wlroots_LIBRARIES}
|
${Wlroots_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,60 +1,20 @@
|
|||||||
#include <stdlib.h>
|
#include "openxr_gl.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
#include <wlr/backend/interface.h>
|
|
||||||
#include <wlr/util/log.h>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct my_backend {
|
|
||||||
struct wlr_backend base;
|
|
||||||
// TODO: any backend‐specific fields
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
static bool backend_start(struct wlr_backend* backend)
|
|
||||||
{
|
|
||||||
(void)backend;
|
|
||||||
// TODO: start event loops, create outputs, inputs, etc.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void backend_destroy(struct wlr_backend* backend)
|
|
||||||
{
|
|
||||||
(void)backend;
|
|
||||||
// TODO: destroy outputs, free everything
|
|
||||||
}
|
|
||||||
|
|
||||||
static int backend_get_drm_fd(struct wlr_backend* backend)
|
|
||||||
{
|
|
||||||
(void)backend;
|
|
||||||
// TODO: return drm FD or -1
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct wlr_backend_impl backend_impl = {
|
|
||||||
.start = backend_start,
|
|
||||||
.destroy = backend_destroy,
|
|
||||||
.get_drm_fd = backend_get_drm_fd,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct wlr_backend* wlr_my_backend_create(
|
struct wlr_backend* wlr_my_backend_create(
|
||||||
struct wl_event_loop* loop, char const* name)
|
struct wl_event_loop* loop, char const* name)
|
||||||
{
|
{
|
||||||
(void)loop;
|
|
||||||
(void)name;
|
(void)name;
|
||||||
struct my_backend* b = (struct my_backend*)calloc(1, sizeof(*b));
|
return wlr_openxr_backend_create(nullptr, loop);
|
||||||
if (!b) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
wlr_backend_init(&b->base, &backend_impl);
|
|
||||||
// TODO: store loop/name, setup
|
|
||||||
return &b->base;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_backend_is_mybackend(struct wlr_backend* backend)
|
bool wlr_backend_is_mybackend(struct wlr_backend* backend)
|
||||||
{
|
{
|
||||||
return backend->impl == &backend_impl;
|
return wlr_backend_is_openxr(backend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
208
src/wlr/openxr_gl.cpp
Normal file
208
src/wlr/openxr_gl.cpp
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
#include "openxr_gl.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <wayland-server-core.h>
|
||||||
|
#include <wlr/backend/interface.h>
|
||||||
|
#include <wlr/interfaces/wlr_output.h>
|
||||||
|
#include <wlr/util/log.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
static void output_destroy(struct wlr_output* wlr_output) { (void)wlr_output; }
|
||||||
|
|
||||||
|
static bool output_test(
|
||||||
|
struct wlr_output* wlr_output, const struct wlr_output_state* state)
|
||||||
|
{
|
||||||
|
(void)wlr_output;
|
||||||
|
(void)state;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_commit(
|
||||||
|
struct wlr_output* wlr_output, const struct wlr_output_state* state)
|
||||||
|
{
|
||||||
|
(void)wlr_output;
|
||||||
|
(void)state;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_drm_format_set* output_get_primary_formats(
|
||||||
|
struct wlr_output* wlr_output, uint32_t buffer_caps)
|
||||||
|
{
|
||||||
|
(void)wlr_output;
|
||||||
|
(void)buffer_caps;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct wlr_output_impl output_impl = {
|
||||||
|
.destroy = output_destroy,
|
||||||
|
.test = output_test,
|
||||||
|
.commit = output_commit,
|
||||||
|
.get_primary_formats = output_get_primary_formats,
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <openxr/openxr.h>
|
||||||
|
#include <openxr/openxr_platform.h>
|
||||||
|
|
||||||
|
struct openxr_backend {
|
||||||
|
wlr_backend base;
|
||||||
|
wl_display* display;
|
||||||
|
XrInstance instance {};
|
||||||
|
XrSession session {};
|
||||||
|
bool started = false;
|
||||||
|
struct wlr_output* output = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool backend_start(wlr_backend* backend)
|
||||||
|
{
|
||||||
|
auto* xr = reinterpret_cast<openxr_backend*>(backend);
|
||||||
|
if (xr->started)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
XrApplicationInfo ai {};
|
||||||
|
std::strncpy(
|
||||||
|
ai.applicationName, "LunarWM", XR_MAX_APPLICATION_NAME_SIZE - 1);
|
||||||
|
ai.applicationVersion = 1;
|
||||||
|
std::strncpy(ai.engineName, "LunarWM", XR_MAX_ENGINE_NAME_SIZE - 1);
|
||||||
|
ai.engineVersion = 1;
|
||||||
|
ai.apiVersion = XR_CURRENT_API_VERSION;
|
||||||
|
|
||||||
|
char const* exts[] = {
|
||||||
|
XR_EXT_DEBUG_UTILS_EXTENSION_NAME,
|
||||||
|
XR_KHR_OPENGL_ENABLE_EXTENSION_NAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
XrInstanceCreateInfo ic { XR_TYPE_INSTANCE_CREATE_INFO };
|
||||||
|
ic.applicationInfo = ai;
|
||||||
|
ic.enabledExtensionCount = sizeof(exts) / sizeof(exts[0]);
|
||||||
|
ic.enabledExtensionNames = exts;
|
||||||
|
|
||||||
|
if (xrCreateInstance(&ic, &xr->instance) != XR_SUCCESS) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to create OpenXR instance");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
XrSystemGetInfo sgi { XR_TYPE_SYSTEM_GET_INFO };
|
||||||
|
sgi.formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY;
|
||||||
|
XrSystemId system_id;
|
||||||
|
if (xrGetSystem(xr->instance, &sgi, &system_id) != XR_SUCCESS) {
|
||||||
|
wlr_log(WLR_ERROR, "xrGetSystem failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PFN_xrGetOpenGLGraphicsRequirementsKHR get_reqs;
|
||||||
|
xrGetInstanceProcAddr(xr->instance, "xrGetOpenGLGraphicsRequirementsKHR",
|
||||||
|
reinterpret_cast<PFN_xrVoidFunction*>(&get_reqs));
|
||||||
|
XrGraphicsRequirementsOpenGLKHR gl_reqs {
|
||||||
|
XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR
|
||||||
|
};
|
||||||
|
get_reqs(xr->instance, system_id, &gl_reqs);
|
||||||
|
|
||||||
|
Display* dpy = XOpenDisplay(nullptr);
|
||||||
|
if (!dpy) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to open X display");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int screen = DefaultScreen(dpy);
|
||||||
|
static int vis_attrs[] = { GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE,
|
||||||
|
GLX_WINDOW_BIT, GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_VISUAL_TYPE,
|
||||||
|
GLX_TRUE_COLOR, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
|
||||||
|
GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, True, None };
|
||||||
|
int fbcount;
|
||||||
|
GLXFBConfig* fbcs = glXChooseFBConfig(dpy, screen, vis_attrs, &fbcount);
|
||||||
|
if (!fbcs || !fbcount) {
|
||||||
|
wlr_log(WLR_ERROR, "No GLXFBConfig found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
GLXFBConfig fbc = fbcs[0];
|
||||||
|
XFree(fbcs);
|
||||||
|
|
||||||
|
XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, fbc);
|
||||||
|
Window root = RootWindow(dpy, screen);
|
||||||
|
XSetWindowAttributes swa;
|
||||||
|
swa.colormap = XCreateColormap(dpy, root, vi->visual, AllocNone);
|
||||||
|
swa.event_mask = ExposureMask;
|
||||||
|
Window win = XCreateWindow(dpy, root, 0, 0, 16, 16, 0, vi->depth,
|
||||||
|
InputOutput, vi->visual, CWColormap | CWEventMask, &swa);
|
||||||
|
GLXContext ctx
|
||||||
|
= glXCreateNewContext(dpy, fbc, GLX_RGBA_TYPE, nullptr, True);
|
||||||
|
glXMakeContextCurrent(dpy, win, win, ctx);
|
||||||
|
|
||||||
|
XrGraphicsBindingOpenGLXlibKHR bind {
|
||||||
|
XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR
|
||||||
|
};
|
||||||
|
bind.xDisplay = dpy;
|
||||||
|
bind.visualid = vi->visualid;
|
||||||
|
bind.glxFBConfig = fbc;
|
||||||
|
bind.glxDrawable = win;
|
||||||
|
bind.glxContext = ctx;
|
||||||
|
|
||||||
|
XrSessionCreateInfo sci { XR_TYPE_SESSION_CREATE_INFO };
|
||||||
|
sci.next = &bind;
|
||||||
|
sci.systemId = system_id;
|
||||||
|
if (xrCreateSession(xr->instance, &sci, &xr->session) != XR_SUCCESS) {
|
||||||
|
wlr_log(WLR_ERROR, "xrCreateSession failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
xr->output = static_cast<wlr_output*>(calloc(1, sizeof(wlr_output)));
|
||||||
|
if (xr->output) {
|
||||||
|
wlr_output_init(xr->output, &xr->base, &output_impl, "OpenXR");
|
||||||
|
wlr_output_create_global(xr->output);
|
||||||
|
}
|
||||||
|
|
||||||
|
xr->started = true;
|
||||||
|
wlr_log(WLR_INFO, "OpenXR backend started");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void backend_destroy(wlr_backend* backend)
|
||||||
|
{
|
||||||
|
auto* xr = reinterpret_cast<openxr_backend*>(backend);
|
||||||
|
if (xr->session) {
|
||||||
|
xrDestroySession(xr->session);
|
||||||
|
}
|
||||||
|
if (xr->instance) {
|
||||||
|
xrDestroyInstance(xr->instance);
|
||||||
|
}
|
||||||
|
free(xr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int backend_get_drm_fd(wlr_backend* backend)
|
||||||
|
{
|
||||||
|
(void)backend;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wlr_backend_impl const backend_impl = {
|
||||||
|
.start = backend_start,
|
||||||
|
.destroy = backend_destroy,
|
||||||
|
.get_drm_fd = backend_get_drm_fd,
|
||||||
|
};
|
||||||
|
|
||||||
|
wlr_backend* wlr_openxr_backend_create(wl_display* display, wl_event_loop* loop)
|
||||||
|
{
|
||||||
|
(void)loop;
|
||||||
|
auto* b = static_cast<openxr_backend*>(calloc(1, sizeof(*b)));
|
||||||
|
if (!b)
|
||||||
|
return nullptr;
|
||||||
|
b->display = display;
|
||||||
|
wlr_backend_init(&b->base, &backend_impl);
|
||||||
|
return &b->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wlr_backend_is_openxr(wlr_backend* backend)
|
||||||
|
{
|
||||||
|
return backend->impl == &backend_impl;
|
||||||
|
}
|
||||||
18
src/wlr/openxr_gl.h
Normal file
18
src/wlr/openxr_gl.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct wlr_backend;
|
||||||
|
struct wl_display;
|
||||||
|
struct wl_event_loop;
|
||||||
|
|
||||||
|
struct wlr_backend* wlr_openxr_backend_create(
|
||||||
|
struct wl_display* display, struct wl_event_loop* loop);
|
||||||
|
|
||||||
|
bool wlr_backend_is_openxr(struct wlr_backend* backend);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user