Refine OpenXR backend formatting
This commit is contained in:
		
							
								
								
									
										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; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user