Skip to content

Commit

Permalink
GS/OpenGL: Use EGL 1.5 platform interface
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Feb 18, 2024
1 parent 4619b7c commit 62d1d2a
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 68 deletions.
13 changes: 9 additions & 4 deletions pcsx2/GS/Renderers/OpenGL/GLContext.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#include "GS/Renderers/OpenGL/GLContext.h"
Expand All @@ -17,6 +17,7 @@
#endif

#include "common/Console.h"
#include "common/Error.h"

#include "glad.h"

Expand All @@ -27,7 +28,7 @@ GLContext::GLContext(const WindowInfo& wi)

GLContext::~GLContext() = default;

std::unique_ptr<GLContext> GLContext::Create(const WindowInfo& wi)
std::unique_ptr<GLContext> GLContext::Create(const WindowInfo& wi, Error* error)
{
// We need at least GL3.3.
static constexpr Version vlist[] = {
Expand All @@ -42,24 +43,28 @@ std::unique_ptr<GLContext> GLContext::Create(const WindowInfo& wi)
};

std::unique_ptr<GLContext> context;
Error local_error;
#if defined(_WIN32)
context = GLContextWGL::Create(wi, vlist);
#elif defined(__APPLE__)
context = GLContextAGL::Create(wi, vlist);
#else // Linux
#if defined(X11_API)
if (wi.type == WindowInfo::Type::X11)
context = GLContextEGLX11::Create(wi, vlist);
context = GLContextEGLX11::Create(wi, vlist, error ? error : &local_error);
#endif

#if defined(WAYLAND_API)
if (wi.type == WindowInfo::Type::Wayland)
context = GLContextEGLWayland::Create(wi, vlist);
context = GLContextEGLWayland::Create(wi, vlist, error ? error : &local_error);
#endif
#endif

if (!context)
{
Console.ErrorFmt("Failed to create GL context: {}", (error ? error : &local_error)->GetDescription());
return nullptr;
}

// NOTE: Not thread-safe. But this is okay, since we're not going to be creating more than one context at a time.
static GLContext* context_being_created;
Expand Down
7 changes: 5 additions & 2 deletions pcsx2/GS/Renderers/OpenGL/GLContext.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#pragma once
Expand All @@ -10,6 +10,8 @@
#include <memory>
#include <vector>

class Error;

class GLContext
{
public:
Expand All @@ -30,12 +32,13 @@ class GLContext
virtual bool ChangeSurface(const WindowInfo& new_wi) = 0;
virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) = 0;
virtual bool SwapBuffers() = 0;
virtual bool IsCurrent() = 0;
virtual bool MakeCurrent() = 0;
virtual bool DoneCurrent() = 0;
virtual bool SetSwapInterval(s32 interval) = 0;
virtual std::unique_ptr<GLContext> CreateSharedContext(const WindowInfo& wi) = 0;

static std::unique_ptr<GLContext> Create(const WindowInfo& wi);
static std::unique_ptr<GLContext> Create(const WindowInfo& wi, Error* error);

protected:
WindowInfo m_wi;
Expand Down
3 changes: 2 additions & 1 deletion pcsx2/GS/Renderers/OpenGL/GLContextAGL.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#pragma once
Expand Down Expand Up @@ -29,6 +29,7 @@ class GLContextAGL final : public GLContext
bool ChangeSurface(const WindowInfo& new_wi) override;
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
bool SwapBuffers() override;
bool IsCurrent() override;
bool MakeCurrent() override;
bool DoneCurrent() override;
bool SetSwapInterval(s32 interval) override;
Expand Down
7 changes: 6 additions & 1 deletion pcsx2/GS/Renderers/OpenGL/GLContextAGL.mm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2002-2023 PCSX2 Dev Team
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
// SPDX-License-Identifier: LGPL-3.0+

#include "GS/Renderers/OpenGL/GLContextAGL.h"
Expand Down Expand Up @@ -111,6 +111,11 @@
return true;
}

bool ContextAGL::IsCurrent()
{
return (m_context != nil && [NSOpenGLContext currentContext] == m_context);
}

bool GLContextAGL::MakeCurrent()
{
[m_context makeCurrentContext];
Expand Down
106 changes: 75 additions & 31 deletions pcsx2/GS/Renderers/OpenGL/GLContextEGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#include "GS/Renderers/OpenGL/GLContextEGL.h"

#include "common/Assertions.h"
#include "common/Console.h"
#include "common/Error.h"

#include <algorithm>
#include <cstring>
Expand All @@ -21,30 +23,32 @@ GLContextEGL::~GLContextEGL()
DestroyContext();
}

std::unique_ptr<GLContext> GLContextEGL::Create(const WindowInfo& wi, std::span<const Version> versions_to_try)
std::unique_ptr<GLContext> GLContextEGL::Create(const WindowInfo& wi, std::span<const Version> versions_to_try, Error* error)
{
std::unique_ptr<GLContextEGL> context = std::make_unique<GLContextEGL>(wi);
if (!context->Initialize(versions_to_try))
if (!context->Initialize(versions_to_try, error))
return nullptr;

return context;
}

bool GLContextEGL::Initialize(std::span<const Version> versions_to_try)
bool GLContextEGL::Initialize(std::span<const Version> versions_to_try, Error* error)
{
if (!gladLoadEGL())
{
Console.Error("Loading GLAD EGL functions failed");
Error::SetStringView(error, "Loading GLAD EGL functions failed");
return false;
}

if (!SetDisplay())
m_display = GetPlatformDisplay(nullptr, error);
if (m_display == EGL_NO_DISPLAY)
return false;

int egl_major, egl_minor;
if (!eglInitialize(m_display, &egl_major, &egl_minor))
{
Console.Error("eglInitialize() failed: %d", eglGetError());
const int gerror = static_cast<int>(eglGetError());
Error::SetStringFmt(error, "eglInitialize() failed: {} (0x{:X})", gerror, gerror);
return false;
}
Console.WriteLn("EGL Version: %d.%d", egl_major, egl_minor);
Expand All @@ -61,21 +65,57 @@ bool GLContextEGL::Initialize(std::span<const Version> versions_to_try)
return true;
}

Error::SetStringView(error, "Failed to create any context versions");
return false;
}

bool GLContextEGL::SetDisplay()
bool GLContextEGL::CheckExtension(const char* name, const char* alt_name, Error* error) const
{
m_display = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wi.display_connection));
if (!m_display)
const char* client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
if (!client_extensions)
{
Console.Error("eglGetDisplay() failed: %d", eglGetError());
Error::SetStringView(error, "EGL_EXT_client_extensions is not supported");
return false;
}

if (!std::strstr(client_extensions, name) && (!alt_name || !std::strstr(client_extensions, alt_name)))
{
Error::SetStringFmt(error, "EGL extension {} is not supported", name);
return false;
}

return true;
}

EGLDisplay GLContextEGL::GetPlatformDisplay(const EGLAttrib* attribs, Error* error)
{
if (!CheckExtension("EGL_MESA_platform_surfaceless", nullptr, error))
return EGL_NO_DISPLAY;

EGLDisplay dpy = eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, m_wi.display_connection, attribs);
if (dpy == EGL_NO_DISPLAY)
{
const EGLint err = eglGetError();
Error::SetStringFmt(error, "eglGetPlatformDisplay() failed: {} (0x{:X})", err, err);
}

return dpy;
}

EGLSurface GLContextEGL::CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error)
{
// for surfaceless
pxAssert(!m_wi.window_handle);
EGLSurface surface = eglCreatePlatformWindowSurface(m_display, config, nullptr, attribs);
if (surface == EGL_NO_SURFACE)
{
const EGLint err = eglGetError();
Error::SetStringFmt(error, "eglCreatePlatformWindowSurface() failed: {} (0x{:X})", err, err);
}

return surface;
}

void* GLContextEGL::GetProcAddress(const char* name)
{
return reinterpret_cast<void*>(eglGetProcAddress(name));
Expand Down Expand Up @@ -133,6 +173,11 @@ bool GLContextEGL::SwapBuffers()
return eglSwapBuffers(m_display, m_surface);
}

bool GLContextEGL::IsCurrent()
{
return m_context && eglGetCurrentContext() == m_context;
}

bool GLContextEGL::MakeCurrent()
{
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
Expand Down Expand Up @@ -166,11 +211,6 @@ std::unique_ptr<GLContext> GLContextEGL::CreateSharedContext(const WindowInfo& w
return context;
}

EGLNativeWindowType GLContextEGL::GetNativeWindow(EGLConfig config)
{
return {};
}

bool GLContextEGL::CreateSurface()
{
if (m_wi.type == WindowInfo::Type::Surfaceless)
Expand All @@ -181,11 +221,11 @@ bool GLContextEGL::CreateSurface()
return CreatePBufferSurface();
}

EGLNativeWindowType native_window = GetNativeWindow(m_config);
m_surface = eglCreateWindowSurface(m_display, m_config, native_window, nullptr);
if (!m_surface)
Error error;
m_surface = CreatePlatformSurface(m_config, nullptr, &error);
if (m_surface == EGL_NO_SURFACE)
{
Console.Error("eglCreateWindowSurface() failed: %d", eglGetError());
Console.ErrorFmt("Failed to create platform surface: {}", error.GetDescription());
return false;
}

Expand Down Expand Up @@ -287,19 +327,21 @@ bool GLContextEGL::CreateContext(const Version& version, EGLContext share_contex
}
configs.resize(static_cast<u32>(num_configs));

m_config = [this, &configs]() {
const auto found_config = std::find_if(std::begin(configs), std::end(configs),
[this](const auto& check_config) { return CheckConfigSurfaceFormat(check_config); });
if (found_config == std::end(configs))
{
Console.Warning("No EGL configs matched exactly, using first.");
return configs.front();
}
else
std::optional<EGLConfig> config;
for (EGLConfig check_config : configs)
{
if (CheckConfigSurfaceFormat(check_config))
{
return *found_config;
config = check_config;
break;
}
}();
}

if (!config.has_value())
{
Console.Warning("No EGL configs matched exactly, using first.");
config = configs.front();
}

const std::array<int, 5> attribs = {
{EGL_CONTEXT_MAJOR_VERSION, version.major_version, EGL_CONTEXT_MINOR_VERSION, version.minor_version, EGL_NONE}};
Expand All @@ -310,14 +352,16 @@ bool GLContextEGL::CreateContext(const Version& version, EGLContext share_contex
return false;
}

m_context = eglCreateContext(m_display, m_config, share_context, attribs.data());
m_context = eglCreateContext(m_display, config.value(), share_context, attribs.data());
if (!m_context)
{
Console.Error("eglCreateContext() failed: %d", eglGetError());
return false;
}

Console.WriteLn("eglCreateContext() succeeded for version %u.%u", version.major_version, version.minor_version);

m_config = config.value();
m_version = version;
return true;
}
Expand Down
11 changes: 7 additions & 4 deletions pcsx2/GS/Renderers/OpenGL/GLContextEGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,25 @@ class GLContextEGL : public GLContext
GLContextEGL(const WindowInfo& wi);
~GLContextEGL() override;

static std::unique_ptr<GLContext> Create(const WindowInfo& wi, std::span<const Version> versions_to_try);
static std::unique_ptr<GLContext> Create(const WindowInfo& wi, std::span<const Version> versions_to_try, Error* error);

void* GetProcAddress(const char* name) override;
virtual bool ChangeSurface(const WindowInfo& new_wi) override;
virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
bool SwapBuffers() override;
bool IsCurrent() override;
bool MakeCurrent() override;
bool DoneCurrent() override;
bool SetSwapInterval(s32 interval) override;
virtual std::unique_ptr<GLContext> CreateSharedContext(const WindowInfo& wi) override;

protected:
virtual bool SetDisplay();
virtual EGLNativeWindowType GetNativeWindow(EGLConfig config);
virtual EGLDisplay GetPlatformDisplay(const EGLAttrib* attribs, Error* error);
virtual EGLSurface CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error);

bool Initialize(std::span<const Version> versions_to_try);
bool CheckExtension(const char* name, const char* alt_name, Error* error) const;

bool Initialize(std::span<const Version> versions_to_try, Error* error);
bool CreateDisplay();
bool CreateContext(const Version& version, EGLContext share_context);
bool CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current);
Expand Down
Loading

0 comments on commit 62d1d2a

Please sign in to comment.