duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

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 }