opengl_context_egl_wayland.cpp (3588B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR PolyForm-Strict-1.0.0) 3 4 #include "opengl_context_egl_wayland.h" 5 6 #include "common/error.h" 7 8 #include <dlfcn.h> 9 10 static const char* WAYLAND_EGL_MODNAME = "libwayland-egl.so.1"; 11 12 OpenGLContextEGLWayland::OpenGLContextEGLWayland(const WindowInfo& wi) : OpenGLContextEGL(wi) 13 { 14 } 15 16 OpenGLContextEGLWayland::~OpenGLContextEGLWayland() 17 { 18 if (m_wl_window) 19 m_wl_egl_window_destroy(m_wl_window); 20 if (m_wl_module) 21 dlclose(m_wl_module); 22 } 23 24 std::unique_ptr<OpenGLContext> OpenGLContextEGLWayland::Create(const WindowInfo& wi, 25 std::span<const Version> versions_to_try, Error* error) 26 { 27 std::unique_ptr<OpenGLContextEGLWayland> context = std::make_unique<OpenGLContextEGLWayland>(wi); 28 if (!context->LoadModule(error) || !context->Initialize(versions_to_try, error)) 29 return nullptr; 30 31 return context; 32 } 33 34 std::unique_ptr<OpenGLContext> OpenGLContextEGLWayland::CreateSharedContext(const WindowInfo& wi, Error* error) 35 { 36 std::unique_ptr<OpenGLContextEGLWayland> context = std::make_unique<OpenGLContextEGLWayland>(wi); 37 context->m_display = m_display; 38 39 if (!context->LoadModule(error) || !context->CreateContextAndSurface(m_version, m_context, false)) 40 return nullptr; 41 42 return context; 43 } 44 45 void OpenGLContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surface_height) 46 { 47 if (m_wl_window) 48 m_wl_egl_window_resize(m_wl_window, new_surface_width, new_surface_height, 0, 0); 49 50 OpenGLContextEGL::ResizeSurface(new_surface_width, new_surface_height); 51 } 52 53 EGLDisplay OpenGLContextEGLWayland::GetPlatformDisplay(Error* error) 54 { 55 EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, "EGL_EXT_platform_wayland"); 56 if (dpy == EGL_NO_DISPLAY) 57 dpy = GetFallbackDisplay(error); 58 59 return dpy; 60 } 61 62 EGLSurface OpenGLContextEGLWayland::CreatePlatformSurface(EGLConfig config, void* win, Error* error) 63 { 64 if (m_wl_window) 65 { 66 m_wl_egl_window_destroy(m_wl_window); 67 m_wl_window = nullptr; 68 } 69 70 m_wl_window = m_wl_egl_window_create(static_cast<wl_surface*>(win), m_wi.surface_width, m_wi.surface_height); 71 if (!m_wl_window) 72 { 73 Error::SetStringView(error, "wl_egl_window_create() failed"); 74 return EGL_NO_SURFACE; 75 } 76 77 EGLSurface surface = TryCreatePlatformSurface(config, m_wl_window, error); 78 if (surface == EGL_NO_SURFACE) 79 { 80 surface = CreateFallbackSurface(config, m_wl_window, error); 81 if (surface == EGL_NO_SURFACE) 82 { 83 m_wl_egl_window_destroy(m_wl_window); 84 m_wl_window = nullptr; 85 } 86 } 87 88 return surface; 89 } 90 91 bool OpenGLContextEGLWayland::LoadModule(Error* error) 92 { 93 m_wl_module = dlopen(WAYLAND_EGL_MODNAME, RTLD_NOW | RTLD_GLOBAL); 94 if (!m_wl_module) 95 { 96 const char* err = dlerror(); 97 Error::SetStringFmt(error, "Loading {} failed: {}", WAYLAND_EGL_MODNAME, err ? err : "<UNKNOWN>"); 98 return false; 99 } 100 101 m_wl_egl_window_create = 102 reinterpret_cast<decltype(m_wl_egl_window_create)>(dlsym(m_wl_module, "wl_egl_window_create")); 103 m_wl_egl_window_destroy = 104 reinterpret_cast<decltype(m_wl_egl_window_destroy)>(dlsym(m_wl_module, "wl_egl_window_destroy")); 105 m_wl_egl_window_resize = 106 reinterpret_cast<decltype(m_wl_egl_window_resize)>(dlsym(m_wl_module, "wl_egl_window_resize")); 107 if (!m_wl_egl_window_create || !m_wl_egl_window_destroy || !m_wl_egl_window_resize) 108 { 109 Error::SetStringFmt(error, "Failed to load one or more functions from {}.", WAYLAND_EGL_MODNAME); 110 return false; 111 } 112 113 return true; 114 }