Apply clang-format-15

This commit is contained in:
Reg Tiangha 2024-06-10 22:29:24 -06:00
parent 3193775201
commit 99b9cec967
No known key found for this signature in database
GPG key ID: 00D437798B1C2970
21 changed files with 1623 additions and 1779 deletions

View file

@ -7,7 +7,7 @@
#define ALWAYS_INLINE __attribute__((always_inline)) inline #define ALWAYS_INLINE __attribute__((always_inline)) inline
#define AssertMsg(cond, msg) assert(cond && msg) #define AssertMsg(cond, msg) assert(cond&& msg)
#define Assert(cond) assert(cond) #define Assert(cond) assert(cond)
#define Panic(msg) assert(false && msg) #define Panic(msg) assert(false && msg)

View file

@ -1,9 +1,9 @@
#include "context.h"
#include "../log.h"
#include "loader.h"
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <stdlib.h> #include <stdlib.h>
#include "../log.h"
#include "context.h"
#include "loader.h"
Log_SetChannel(GL::Context); Log_SetChannel(GL::Context);
#if defined(_WIN32) #if defined(_WIN32)
@ -20,8 +20,7 @@ Log_SetChannel(GL::Context);
namespace GL { namespace GL {
static bool ShouldPreferESContext() static bool ShouldPreferESContext() {
{
#ifndef _MSC_VER #ifndef _MSC_VER
const char* value = std::getenv("PREFER_GLES_CONTEXT"); const char* value = std::getenv("PREFER_GLES_CONTEXT");
return (value && strcmp(value, "1") == 0); return (value && strcmp(value, "1") == 0);
@ -37,26 +36,22 @@ Context::Context(const WindowInfo& wi) : m_wi(wi) {}
Context::~Context() = default; Context::~Context() = default;
std::vector<Context::FullscreenModeInfo> Context::EnumerateFullscreenModes() std::vector<Context::FullscreenModeInfo> Context::EnumerateFullscreenModes() {
{
return {}; return {};
} }
std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version* versions_to_try, std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try) size_t num_versions_to_try) {
{ if (ShouldPreferESContext()) {
if (ShouldPreferESContext())
{
// move ES versions to the front // move ES versions to the front
Version* new_versions_to_try = static_cast<Version*>(alloca(sizeof(Version) * num_versions_to_try)); Version* new_versions_to_try =
static_cast<Version*>(alloca(sizeof(Version) * num_versions_to_try));
size_t count = 0; size_t count = 0;
for (size_t i = 0; i < num_versions_to_try; i++) for (size_t i = 0; i < num_versions_to_try; i++) {
{
if (versions_to_try[i].profile == Profile::ES) if (versions_to_try[i].profile == Profile::ES)
new_versions_to_try[count++] = versions_to_try[i]; new_versions_to_try[count++] = versions_to_try[i];
} }
for (size_t i = 0; i < num_versions_to_try; i++) for (size_t i = 0; i < num_versions_to_try; i++) {
{
if (versions_to_try[i].profile != Profile::ES) if (versions_to_try[i].profile != Profile::ES)
new_versions_to_try[count++] = versions_to_try[i]; new_versions_to_try[count++] = versions_to_try[i];
} }
@ -69,8 +64,7 @@ std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version
#elif defined(__APPLE__) #elif defined(__APPLE__)
context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try); context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try);
#else #else
if (wi.type == WindowInfo::Type::X11) if (wi.type == WindowInfo::Type::X11) {
{
const char* use_egl_x11 = std::getenv("USE_EGL_X11"); const char* use_egl_x11 = std::getenv("USE_EGL_X11");
if (use_egl_x11 && std::strcmp(use_egl_x11, "1") == 0) if (use_egl_x11 && std::strcmp(use_egl_x11, "1") == 0)
context = ContextEGLX11::Create(wi, versions_to_try, num_versions_to_try); context = ContextEGLX11::Create(wi, versions_to_try, num_versions_to_try);
@ -93,8 +87,8 @@ std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version
static Context* context_being_created; static Context* context_being_created;
context_being_created = context.get(); context_being_created = context.get();
if (!gladLoadGLLoader([](const char* name) { return context_being_created->GetProcAddress(name); })) if (!gladLoadGLLoader(
{ [](const char* name) { return context_being_created->GetProcAddress(name); })) {
Log_ErrorPrintf("Failed to load GL functions for GLAD"); Log_ErrorPrintf("Failed to load GL functions for GLAD");
return nullptr; return nullptr;
} }
@ -102,7 +96,8 @@ std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version
const char* gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); const char* gl_vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
const char* gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); const char* gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
const char* gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); const char* gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
const char* gl_shading_language_version = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION)); const char* gl_shading_language_version =
reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
Log_InfoPrintf("GL_VENDOR: %s", gl_vendor); Log_InfoPrintf("GL_VENDOR: %s", gl_vendor);
Log_InfoPrintf("GL_RENDERER: %s", gl_renderer); Log_InfoPrintf("GL_RENDERER: %s", gl_renderer);
Log_InfoPrintf("GL_VERSION: %s", gl_version); Log_InfoPrintf("GL_VERSION: %s", gl_version);
@ -111,8 +106,7 @@ std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version
return context; return context;
} }
const std::array<Context::Version, 11>& Context::GetAllDesktopVersionsList() const std::array<Context::Version, 11>& Context::GetAllDesktopVersionsList() {
{
static constexpr std::array<Version, 11> vlist = {{{Profile::Core, 4, 6}, static constexpr std::array<Version, 11> vlist = {{{Profile::Core, 4, 6},
{Profile::Core, 4, 5}, {Profile::Core, 4, 5},
{Profile::Core, 4, 4}, {Profile::Core, 4, 4},
@ -127,8 +121,7 @@ const std::array<Context::Version, 11>& Context::GetAllDesktopVersionsList()
return vlist; return vlist;
} }
const std::array<Context::Version, 12>& Context::GetAllDesktopVersionsListWithFallback() const std::array<Context::Version, 12>& Context::GetAllDesktopVersionsListWithFallback() {
{
static constexpr std::array<Version, 12> vlist = {{{Profile::Core, 4, 6}, static constexpr std::array<Version, 12> vlist = {{{Profile::Core, 4, 6},
{Profile::Core, 4, 5}, {Profile::Core, 4, 5},
{Profile::Core, 4, 4}, {Profile::Core, 4, 4},
@ -144,15 +137,13 @@ const std::array<Context::Version, 12>& Context::GetAllDesktopVersionsListWithFa
return vlist; return vlist;
} }
const std::array<Context::Version, 4>& Context::GetAllESVersionsList() const std::array<Context::Version, 4>& Context::GetAllESVersionsList() {
{
static constexpr std::array<Version, 4> vlist = { static constexpr std::array<Version, 4> vlist = {
{{Profile::ES, 3, 2}, {Profile::ES, 3, 1}, {Profile::ES, 3, 0}, {Profile::ES, 2, 0}}}; {{Profile::ES, 3, 2}, {Profile::ES, 3, 1}, {Profile::ES, 3, 0}, {Profile::ES, 2, 0}}};
return vlist; return vlist;
} }
const std::array<Context::Version, 16>& Context::GetAllVersionsList() const std::array<Context::Version, 16>& Context::GetAllVersionsList() {
{
static constexpr std::array<Version, 16> vlist = {{{Profile::Core, 4, 6}, static constexpr std::array<Version, 16> vlist = {{{Profile::Core, 4, 6},
{Profile::Core, 4, 5}, {Profile::Core, 4, 5},
{Profile::Core, 4, 4}, {Profile::Core, 4, 4},

View file

@ -1,44 +1,46 @@
#pragma once #pragma once
#include "../duckstation_compat.h"
#include "../window_info.h"
#include <array> #include <array>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "../duckstation_compat.h"
#include "../window_info.h"
namespace GL { namespace GL {
using namespace citra; using namespace citra;
class Context class Context {
{
public: public:
Context(const WindowInfo& wi); Context(const WindowInfo& wi);
virtual ~Context(); virtual ~Context();
enum class Profile enum class Profile { NoProfile, Core, ES };
{
NoProfile,
Core,
ES
};
struct Version struct Version {
{
Profile profile; Profile profile;
int major_version; int major_version;
int minor_version; int minor_version;
}; };
struct FullscreenModeInfo struct FullscreenModeInfo {
{
u32 width; u32 width;
u32 height; u32 height;
float refresh_rate; float refresh_rate;
}; };
ALWAYS_INLINE const WindowInfo& GetWindowInfo() const { return m_wi; } ALWAYS_INLINE const WindowInfo& GetWindowInfo() const {
ALWAYS_INLINE bool IsGLES() const { return (m_version.profile == Profile::ES); } return m_wi;
ALWAYS_INLINE u32 GetSurfaceWidth() const { return m_wi.surface_width; } }
ALWAYS_INLINE u32 GetSurfaceHeight() const { return m_wi.surface_height; } ALWAYS_INLINE bool IsGLES() const {
ALWAYS_INLINE WindowInfo::SurfaceFormat GetSurfaceFormat() const { return m_wi.surface_format; } return (m_version.profile == Profile::ES);
}
ALWAYS_INLINE u32 GetSurfaceWidth() const {
return m_wi.surface_width;
}
ALWAYS_INLINE u32 GetSurfaceHeight() const {
return m_wi.surface_height;
}
ALWAYS_INLINE WindowInfo::SurfaceFormat GetSurfaceFormat() const {
return m_wi.surface_format;
}
virtual void* GetProcAddress(const char* name) = 0; virtual void* GetProcAddress(const char* name) = 0;
virtual bool ChangeSurface(const WindowInfo& new_wi) = 0; virtual bool ChangeSurface(const WindowInfo& new_wi) = 0;
@ -54,13 +56,15 @@ public:
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try, static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try); size_t num_versions_to_try);
template<size_t N> template <size_t N>
static std::unique_ptr<Context> Create(const WindowInfo& wi, const std::array<Version, N>& versions_to_try) static std::unique_ptr<Context> Create(const WindowInfo& wi,
{ const std::array<Version, N>& versions_to_try) {
return Create(wi, versions_to_try.data(), versions_to_try.size()); return Create(wi, versions_to_try.data(), versions_to_try.size());
} }
static std::unique_ptr<Context> Create(const WindowInfo& wi) { return Create(wi, GetAllVersionsList()); } static std::unique_ptr<Context> Create(const WindowInfo& wi) {
return Create(wi, GetAllVersionsList());
}
static const std::array<Version, 11>& GetAllDesktopVersionsList(); static const std::array<Version, 11>& GetAllDesktopVersionsList();
static const std::array<Version, 12>& GetAllDesktopVersionsListWithFallback(); static const std::array<Version, 12>& GetAllDesktopVersionsListWithFallback();

View file

@ -14,8 +14,7 @@ struct NSView;
namespace GL { namespace GL {
using namespace melonDS; using namespace melonDS;
class ContextAGL final : public Context class ContextAGL final : public Context {
{
public: public:
ContextAGL(const WindowInfo& wi); ContextAGL(const WindowInfo& wi);
~ContextAGL() override; ~ContextAGL() override;
@ -33,7 +32,9 @@ public:
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override; std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
private: private:
ALWAYS_INLINE NSView* GetView() const { return static_cast<NSView*>((__bridge NSView*)m_wi.window_handle); } ALWAYS_INLINE NSView* GetView() const {
return static_cast<NSView*>((__bridge NSView*)m_wi.window_handle);
}
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
bool CreateContext(NSOpenGLContext* share_context, int profile, bool make_current); bool CreateContext(NSOpenGLContext* share_context, int profile, bool make_current);

View file

@ -1,23 +1,21 @@
#include "context_egl.h" #include <cstring>
#include "../log.h"
#include "../duckstation_compat.h"
#include <optional> #include <optional>
#include <vector> #include <vector>
#include <cstring> #include "../duckstation_compat.h"
#include "../log.h"
#include "context_egl.h"
Log_SetChannel(GL::ContextEGL); Log_SetChannel(GL::ContextEGL);
namespace GL { namespace GL {
ContextEGL::ContextEGL(const WindowInfo& wi) : Context(wi) {} ContextEGL::ContextEGL(const WindowInfo& wi) : Context(wi) {}
ContextEGL::~ContextEGL() ContextEGL::~ContextEGL() {
{
DestroySurface(); DestroySurface();
DestroyContext(); DestroyContext();
} }
std::unique_ptr<Context> ContextEGL::Create(const WindowInfo& wi, const Version* versions_to_try, std::unique_ptr<Context> ContextEGL::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try) size_t num_versions_to_try) {
{
std::unique_ptr<ContextEGL> context = std::make_unique<ContextEGL>(wi); std::unique_ptr<ContextEGL> context = std::make_unique<ContextEGL>(wi);
if (!context->Initialize(versions_to_try, num_versions_to_try)) if (!context->Initialize(versions_to_try, num_versions_to_try))
return nullptr; return nullptr;
@ -25,10 +23,8 @@ std::unique_ptr<Context> ContextEGL::Create(const WindowInfo& wi, const Version*
return context; return context;
} }
bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) {
{ if (!gladLoadEGL()) {
if (!gladLoadEGL())
{
Log_ErrorPrintf("Loading GLAD EGL functions failed"); Log_ErrorPrintf("Loading GLAD EGL functions failed");
return false; return false;
} }
@ -37,24 +33,22 @@ bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_
return false; return false;
int egl_major, egl_minor; int egl_major, egl_minor;
if (!eglInitialize(m_display, &egl_major, &egl_minor)) if (!eglInitialize(m_display, &egl_major, &egl_minor)) {
{
Log_ErrorPrintf("eglInitialize() failed: %d", eglGetError()); Log_ErrorPrintf("eglInitialize() failed: %d", eglGetError());
return false; return false;
} }
Log_InfoPrintf("EGL Version: %d.%d", egl_major, egl_minor); Log_InfoPrintf("EGL Version: %d.%d", egl_major, egl_minor);
const char* extensions = eglQueryString(m_display, EGL_EXTENSIONS); const char* extensions = eglQueryString(m_display, EGL_EXTENSIONS);
if (extensions) if (extensions) {
{
Log_InfoPrintf("EGL Extensions: %s", extensions); Log_InfoPrintf("EGL Extensions: %s", extensions);
m_supports_surfaceless = std::strstr(extensions, "EGL_KHR_surfaceless_context") != nullptr; m_supports_surfaceless = std::strstr(extensions, "EGL_KHR_surfaceless_context") != nullptr;
} }
if (!m_supports_surfaceless) if (!m_supports_surfaceless)
Log_WarningPrint("EGL implementation does not support surfaceless contexts, emulating with pbuffers"); Log_WarningPrint(
"EGL implementation does not support surfaceless contexts, emulating with pbuffers");
for (size_t i = 0; i < num_versions_to_try; i++) for (size_t i = 0; i < num_versions_to_try; i++) {
{
if (CreateContextAndSurface(versions_to_try[i], nullptr, true)) if (CreateContextAndSurface(versions_to_try[i], nullptr, true))
return true; return true;
} }
@ -62,11 +56,9 @@ bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_
return false; return false;
} }
bool ContextEGL::SetDisplay() bool ContextEGL::SetDisplay() {
{
m_display = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wi.display_connection)); m_display = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wi.display_connection));
if (!m_display) if (!m_display) {
{
Log_ErrorPrintf("eglGetDisplay() failed: %d", eglGetError()); Log_ErrorPrintf("eglGetDisplay() failed: %d", eglGetError());
return false; return false;
} }
@ -74,19 +66,16 @@ bool ContextEGL::SetDisplay()
return true; return true;
} }
void* ContextEGL::GetProcAddress(const char* name) void* ContextEGL::GetProcAddress(const char* name) {
{
return reinterpret_cast<void*>(eglGetProcAddress(name)); return reinterpret_cast<void*>(eglGetProcAddress(name));
} }
bool ContextEGL::ChangeSurface(const WindowInfo& new_wi) bool ContextEGL::ChangeSurface(const WindowInfo& new_wi) {
{
const bool was_current = (eglGetCurrentContext() == m_context); const bool was_current = (eglGetCurrentContext() == m_context);
if (was_current) if (was_current)
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_surface != EGL_NO_SURFACE) if (m_surface != EGL_NO_SURFACE) {
{
eglDestroySurface(m_display, m_surface); eglDestroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE; m_surface = EGL_NO_SURFACE;
} }
@ -95,8 +84,7 @@ bool ContextEGL::ChangeSurface(const WindowInfo& new_wi)
if (!CreateSurface()) if (!CreateSurface())
return false; return false;
if (was_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) if (was_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) {
{
Log_ErrorPrintf("Failed to make context current again after surface change"); Log_ErrorPrintf("Failed to make context current again after surface change");
return false; return false;
} }
@ -104,20 +92,15 @@ bool ContextEGL::ChangeSurface(const WindowInfo& new_wi)
return true; return true;
} }
void ContextEGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) void ContextEGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) {
{ if (new_surface_width == 0 && new_surface_height == 0) {
if (new_surface_width == 0 && new_surface_height == 0)
{
EGLint surface_width, surface_height; EGLint surface_width, surface_height;
if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) && if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) &&
eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) {
{
m_wi.surface_width = static_cast<u32>(surface_width); m_wi.surface_width = static_cast<u32>(surface_width);
m_wi.surface_height = static_cast<u32>(surface_height); m_wi.surface_height = static_cast<u32>(surface_height);
return; return;
} } else {
else
{
Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError()); Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError());
} }
} }
@ -126,15 +109,12 @@ void ContextEGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_he
m_wi.surface_height = new_surface_height; m_wi.surface_height = new_surface_height;
} }
bool ContextEGL::SwapBuffers() bool ContextEGL::SwapBuffers() {
{
return eglSwapBuffers(m_display, m_surface); return eglSwapBuffers(m_display, m_surface);
} }
bool ContextEGL::MakeCurrent() bool ContextEGL::MakeCurrent() {
{ if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context)) {
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
{
Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError()); Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError());
return false; return false;
} }
@ -142,18 +122,15 @@ bool ContextEGL::MakeCurrent()
return true; return true;
} }
bool ContextEGL::DoneCurrent() bool ContextEGL::DoneCurrent() {
{
return eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); return eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
} }
bool ContextEGL::SetSwapInterval(s32 interval) bool ContextEGL::SetSwapInterval(s32 interval) {
{
return eglSwapInterval(m_display, interval); return eglSwapInterval(m_display, interval);
} }
std::unique_ptr<Context> ContextEGL::CreateSharedContext(const WindowInfo& wi) std::unique_ptr<Context> ContextEGL::CreateSharedContext(const WindowInfo& wi) {
{
std::unique_ptr<ContextEGL> context = std::make_unique<ContextEGL>(wi); std::unique_ptr<ContextEGL> context = std::make_unique<ContextEGL>(wi);
context->m_display = m_display; context->m_display = m_display;
context->m_supports_surfaceless = m_supports_surfaceless; context->m_supports_surfaceless = m_supports_surfaceless;
@ -164,15 +141,12 @@ std::unique_ptr<Context> ContextEGL::CreateSharedContext(const WindowInfo& wi)
return context; return context;
} }
EGLNativeWindowType ContextEGL::GetNativeWindow(EGLConfig config) EGLNativeWindowType ContextEGL::GetNativeWindow(EGLConfig config) {
{
return {}; return {};
} }
bool ContextEGL::CreateSurface() bool ContextEGL::CreateSurface() {
{ if (m_wi.type == WindowInfo::Type::Surfaceless) {
if (m_wi.type == WindowInfo::Type::Surfaceless)
{
if (m_supports_surfaceless) if (m_supports_surfaceless)
return true; return true;
else else
@ -181,8 +155,7 @@ bool ContextEGL::CreateSurface()
EGLNativeWindowType native_window = GetNativeWindow(m_config); EGLNativeWindowType native_window = GetNativeWindow(m_config);
m_surface = eglCreateWindowSurface(m_display, m_config, native_window, nullptr); m_surface = eglCreateWindowSurface(m_display, m_config, native_window, nullptr);
if (!m_surface) if (!m_surface) {
{
Log_ErrorPrintf("eglCreateWindowSurface() failed: %d", eglGetError()); Log_ErrorPrintf("eglCreateWindowSurface() failed: %d", eglGetError());
return false; return false;
} }
@ -190,21 +163,17 @@ bool ContextEGL::CreateSurface()
// Some implementations may require the size to be queried at runtime. // Some implementations may require the size to be queried at runtime.
EGLint surface_width, surface_height; EGLint surface_width, surface_height;
if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) && if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) &&
eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) {
{
m_wi.surface_width = static_cast<u32>(surface_width); m_wi.surface_width = static_cast<u32>(surface_width);
m_wi.surface_height = static_cast<u32>(surface_height); m_wi.surface_height = static_cast<u32>(surface_height);
} } else {
else
{
Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError()); Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError());
} }
return true; return true;
} }
bool ContextEGL::CreatePBufferSurface() bool ContextEGL::CreatePBufferSurface() {
{
const u32 width = std::max<u32>(m_wi.surface_width, 1); const u32 width = std::max<u32>(m_wi.surface_width, 1);
const u32 height = std::max<u32>(m_wi.surface_height, 1); const u32 height = std::max<u32>(m_wi.surface_height, 1);
@ -214,8 +183,7 @@ bool ContextEGL::CreatePBufferSurface()
}; };
m_surface = eglCreatePbufferSurface(m_display, m_config, attrib_list); m_surface = eglCreatePbufferSurface(m_display, m_config, attrib_list);
if (!m_surface) if (!m_surface) {
{
Log_ErrorPrintf("eglCreatePbufferSurface() failed: %d", eglGetError()); Log_ErrorPrintf("eglCreatePbufferSurface() failed: %d", eglGetError());
return false; return false;
} }
@ -224,19 +192,17 @@ bool ContextEGL::CreatePBufferSurface()
return true; return true;
} }
bool ContextEGL::CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const bool ContextEGL::CheckConfigSurfaceFormat(EGLConfig config,
{ WindowInfo::SurfaceFormat format) const {
int red_size, green_size, blue_size, alpha_size; int red_size, green_size, blue_size, alpha_size;
if (!eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &red_size) || if (!eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &red_size) ||
!eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &green_size) || !eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &green_size) ||
!eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &blue_size) || !eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &blue_size) ||
!eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &alpha_size)) !eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &alpha_size)) {
{
return false; return false;
} }
switch (format) switch (format) {
{
case WindowInfo::SurfaceFormat::Auto: case WindowInfo::SurfaceFormat::Auto:
return true; return true;
@ -254,48 +220,44 @@ bool ContextEGL::CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceF
} }
} }
void ContextEGL::DestroyContext() void ContextEGL::DestroyContext() {
{
if (eglGetCurrentContext() == m_context) if (eglGetCurrentContext() == m_context)
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_context != EGL_NO_CONTEXT) if (m_context != EGL_NO_CONTEXT) {
{
eglDestroyContext(m_display, m_context); eglDestroyContext(m_display, m_context);
m_context = EGL_NO_CONTEXT; m_context = EGL_NO_CONTEXT;
} }
} }
void ContextEGL::DestroySurface() void ContextEGL::DestroySurface() {
{
if (eglGetCurrentSurface(EGL_DRAW) == m_surface) if (eglGetCurrentSurface(EGL_DRAW) == m_surface)
eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (m_surface != EGL_NO_SURFACE) if (m_surface != EGL_NO_SURFACE) {
{
eglDestroySurface(m_display, m_surface); eglDestroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE; m_surface = EGL_NO_SURFACE;
} }
} }
bool ContextEGL::CreateContext(const Version& version, EGLContext share_context) bool ContextEGL::CreateContext(const Version& version, EGLContext share_context) {
{ Log_DevPrintf("Trying version %u.%u (%s)", version.major_version, version.minor_version,
Log_DevPrintf( version.profile == Context::Profile::ES
"Trying version %u.%u (%s)", version.major_version, version.minor_version, ? "ES"
version.profile == Context::Profile::ES ? "ES" : (version.profile == Context::Profile::Core ? "Core" : "None")); : (version.profile == Context::Profile::Core ? "Core" : "None"));
int surface_attribs[16] = { int surface_attribs[16] = {
EGL_RENDERABLE_TYPE, EGL_RENDERABLE_TYPE,
(version.profile == Profile::ES) ? (version.profile == Profile::ES)
((version.major_version >= 3) ? EGL_OPENGL_ES3_BIT : ? ((version.major_version >= 3)
((version.major_version == 2) ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_ES_BIT)) : ? EGL_OPENGL_ES3_BIT
EGL_OPENGL_BIT, : ((version.major_version == 2) ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_ES_BIT))
: EGL_OPENGL_BIT,
EGL_SURFACE_TYPE, EGL_SURFACE_TYPE,
(m_wi.type != WindowInfo::Type::Surfaceless) ? EGL_WINDOW_BIT : 0, (m_wi.type != WindowInfo::Type::Surfaceless) ? EGL_WINDOW_BIT : 0,
}; };
int nsurface_attribs = 4; int nsurface_attribs = 4;
switch (m_wi.surface_format) switch (m_wi.surface_format) {
{
case WindowInfo::SurfaceFormat::RGB8: case WindowInfo::SurfaceFormat::RGB8:
surface_attribs[nsurface_attribs++] = EGL_RED_SIZE; surface_attribs[nsurface_attribs++] = EGL_RED_SIZE;
surface_attribs[nsurface_attribs++] = 8; surface_attribs[nsurface_attribs++] = 8;
@ -337,40 +299,35 @@ bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
surface_attribs[nsurface_attribs++] = 0; surface_attribs[nsurface_attribs++] = 0;
EGLint num_configs; EGLint num_configs;
if (!eglChooseConfig(m_display, surface_attribs, nullptr, 0, &num_configs) || num_configs == 0) if (!eglChooseConfig(m_display, surface_attribs, nullptr, 0, &num_configs) ||
{ num_configs == 0) {
Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError()); Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError());
return false; return false;
} }
std::vector<EGLConfig> configs(static_cast<u32>(num_configs)); std::vector<EGLConfig> configs(static_cast<u32>(num_configs));
if (!eglChooseConfig(m_display, surface_attribs, configs.data(), num_configs, &num_configs)) if (!eglChooseConfig(m_display, surface_attribs, configs.data(), num_configs, &num_configs)) {
{
Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError()); Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError());
return false; return false;
} }
configs.resize(static_cast<u32>(num_configs)); configs.resize(static_cast<u32>(num_configs));
std::optional<EGLConfig> config; std::optional<EGLConfig> config;
for (EGLConfig check_config : configs) for (EGLConfig check_config : configs) {
{ if (CheckConfigSurfaceFormat(check_config, m_wi.surface_format)) {
if (CheckConfigSurfaceFormat(check_config, m_wi.surface_format))
{
config = check_config; config = check_config;
break; break;
} }
} }
if (!config.has_value()) if (!config.has_value()) {
{
Log_WarningPrintf("No EGL configs matched exactly, using first."); Log_WarningPrintf("No EGL configs matched exactly, using first.");
config = configs.front(); config = configs.front();
} }
int attribs[8]; int attribs[8];
int nattribs = 0; int nattribs = 0;
if (version.profile != Profile::NoProfile) if (version.profile != Profile::NoProfile) {
{
attribs[nattribs++] = EGL_CONTEXT_MAJOR_VERSION; attribs[nattribs++] = EGL_CONTEXT_MAJOR_VERSION;
attribs[nattribs++] = version.major_version; attribs[nattribs++] = version.major_version;
attribs[nattribs++] = EGL_CONTEXT_MINOR_VERSION; attribs[nattribs++] = EGL_CONTEXT_MINOR_VERSION;
@ -379,46 +336,43 @@ bool ContextEGL::CreateContext(const Version& version, EGLContext share_context)
attribs[nattribs++] = EGL_NONE; attribs[nattribs++] = EGL_NONE;
attribs[nattribs++] = 0; attribs[nattribs++] = 0;
if (!eglBindAPI((version.profile == Profile::ES) ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) if (!eglBindAPI((version.profile == Profile::ES) ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) {
{ Log_ErrorPrintf("eglBindAPI(%s) failed",
Log_ErrorPrintf("eglBindAPI(%s) failed", (version.profile == Profile::ES) ? "EGL_OPENGL_ES_API" : "EGL_OPENGL_API"); (version.profile == Profile::ES) ? "EGL_OPENGL_ES_API" : "EGL_OPENGL_API");
return false; return false;
} }
m_context = eglCreateContext(m_display, config.value(), share_context, attribs); m_context = eglCreateContext(m_display, config.value(), share_context, attribs);
if (!m_context) if (!m_context) {
{
Log_ErrorPrintf("eglCreateContext() failed: %d", eglGetError()); Log_ErrorPrintf("eglCreateContext() failed: %d", eglGetError());
return false; return false;
} }
Log_InfoPrintf( Log_InfoPrintf("Got version %u.%u (%s)", version.major_version, version.minor_version,
"Got version %u.%u (%s)", version.major_version, version.minor_version, version.profile == Context::Profile::ES
version.profile == Context::Profile::ES ? "ES" : (version.profile == Context::Profile::Core ? "Core" : "None")); ? "ES"
: (version.profile == Context::Profile::Core ? "Core" : "None"));
m_config = config.value(); m_config = config.value();
m_version = version; m_version = version;
return true; return true;
} }
bool ContextEGL::CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current) bool ContextEGL::CreateContextAndSurface(const Version& version, EGLContext share_context,
{ bool make_current) {
if (!CreateContext(version, share_context)) if (!CreateContext(version, share_context))
return false; return false;
if (!CreateSurface()) if (!CreateSurface()) {
{
Log_ErrorPrintf("Failed to create surface for context"); Log_ErrorPrintf("Failed to create surface for context");
eglDestroyContext(m_display, m_context); eglDestroyContext(m_display, m_context);
m_context = EGL_NO_CONTEXT; m_context = EGL_NO_CONTEXT;
return false; return false;
} }
if (make_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) if (make_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) {
{
Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError()); Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError());
if (m_surface != EGL_NO_SURFACE) if (m_surface != EGL_NO_SURFACE) {
{
eglDestroySurface(m_display, m_surface); eglDestroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE; m_surface = EGL_NO_SURFACE;
} }

View file

@ -1,11 +1,10 @@
#pragma once #pragma once
#include "context.h"
#include "../../../../../externals/glad/src/glad_egl.h" #include "../../../../../externals/glad/src/glad_egl.h"
#include "context.h"
namespace GL { namespace GL {
class ContextEGL : public Context class ContextEGL : public Context {
{
public: public:
ContextEGL(const WindowInfo& wi); ContextEGL(const WindowInfo& wi);
~ContextEGL() override; ~ContextEGL() override;
@ -29,7 +28,8 @@ protected:
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
bool CreateDisplay(); bool CreateDisplay();
bool CreateContext(const Version& version, EGLContext share_context); bool CreateContext(const Version& version, EGLContext share_context);
bool CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current); bool CreateContextAndSurface(const Version& version, EGLContext share_context,
bool make_current);
bool CreateSurface(); bool CreateSurface();
bool CreatePBufferSurface(); bool CreatePBufferSurface();
bool CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const; bool CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const;

View file

@ -1,23 +1,22 @@
#include "context_egl_wayland.h"
#include "../log.h"
#include <dlfcn.h> #include <dlfcn.h>
#include "../log.h"
#include "context_egl_wayland.h"
Log_SetChannel(ContextEGLWayland); Log_SetChannel(ContextEGLWayland);
namespace GL { namespace GL {
static const char* WAYLAND_EGL_MODNAME = "libwayland-egl.so.1"; static const char* WAYLAND_EGL_MODNAME = "libwayland-egl.so.1";
ContextEGLWayland::ContextEGLWayland(const WindowInfo& wi) : ContextEGL(wi) {} ContextEGLWayland::ContextEGLWayland(const WindowInfo& wi) : ContextEGL(wi) {}
ContextEGLWayland::~ContextEGLWayland() ContextEGLWayland::~ContextEGLWayland() {
{
if (m_wl_window) if (m_wl_window)
m_wl_egl_window_destroy(m_wl_window); m_wl_egl_window_destroy(m_wl_window);
if (m_wl_module) if (m_wl_module)
dlclose(m_wl_module); dlclose(m_wl_module);
} }
std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi, const Version* versions_to_try, std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi,
size_t num_versions_to_try) const Version* versions_to_try,
{ size_t num_versions_to_try) {
std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi); std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
if (!context->LoadModule() || !context->Initialize(versions_to_try, num_versions_to_try)) if (!context->LoadModule() || !context->Initialize(versions_to_try, num_versions_to_try))
return nullptr; return nullptr;
@ -25,8 +24,7 @@ std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi, const V
return context; return context;
} }
std::unique_ptr<Context> ContextEGLWayland::CreateSharedContext(const WindowInfo& wi) std::unique_ptr<Context> ContextEGLWayland::CreateSharedContext(const WindowInfo& wi) {
{
std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi); std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
context->m_display = m_display; context->m_display = m_display;
@ -36,47 +34,41 @@ std::unique_ptr<Context> ContextEGLWayland::CreateSharedContext(const WindowInfo
return context; return context;
} }
void ContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surface_height) void ContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surface_height) {
{
if (m_wl_window) if (m_wl_window)
m_wl_egl_window_resize(m_wl_window, new_surface_width, new_surface_height, 0, 0); m_wl_egl_window_resize(m_wl_window, new_surface_width, new_surface_height, 0, 0);
ContextEGL::ResizeSurface(new_surface_width, new_surface_height); ContextEGL::ResizeSurface(new_surface_width, new_surface_height);
} }
EGLNativeWindowType ContextEGLWayland::GetNativeWindow(EGLConfig config) EGLNativeWindowType ContextEGLWayland::GetNativeWindow(EGLConfig config) {
{ if (m_wl_window) {
if (m_wl_window)
{
m_wl_egl_window_destroy(m_wl_window); m_wl_egl_window_destroy(m_wl_window);
m_wl_window = nullptr; m_wl_window = nullptr;
} }
m_wl_window = m_wl_window = m_wl_egl_window_create(static_cast<wl_surface*>(m_wi.window_handle),
m_wl_egl_window_create(static_cast<wl_surface*>(m_wi.window_handle), m_wi.surface_width, m_wi.surface_height); m_wi.surface_width, m_wi.surface_height);
if (!m_wl_window) if (!m_wl_window)
return {}; return {};
return reinterpret_cast<EGLNativeWindowType>(m_wl_window); return reinterpret_cast<EGLNativeWindowType>(m_wl_window);
} }
bool ContextEGLWayland::LoadModule() bool ContextEGLWayland::LoadModule() {
{
m_wl_module = dlopen(WAYLAND_EGL_MODNAME, RTLD_NOW | RTLD_GLOBAL); m_wl_module = dlopen(WAYLAND_EGL_MODNAME, RTLD_NOW | RTLD_GLOBAL);
if (!m_wl_module) if (!m_wl_module) {
{
Log_ErrorPrintf("Failed to load %s.", WAYLAND_EGL_MODNAME); Log_ErrorPrintf("Failed to load %s.", WAYLAND_EGL_MODNAME);
return false; return false;
} }
m_wl_egl_window_create = m_wl_egl_window_create = reinterpret_cast<decltype(m_wl_egl_window_create)>(
reinterpret_cast<decltype(m_wl_egl_window_create)>(dlsym(m_wl_module, "wl_egl_window_create")); dlsym(m_wl_module, "wl_egl_window_create"));
m_wl_egl_window_destroy = m_wl_egl_window_destroy = reinterpret_cast<decltype(m_wl_egl_window_destroy)>(
reinterpret_cast<decltype(m_wl_egl_window_destroy)>(dlsym(m_wl_module, "wl_egl_window_destroy")); dlsym(m_wl_module, "wl_egl_window_destroy"));
m_wl_egl_window_resize = m_wl_egl_window_resize = reinterpret_cast<decltype(m_wl_egl_window_resize)>(
reinterpret_cast<decltype(m_wl_egl_window_resize)>(dlsym(m_wl_module, "wl_egl_window_resize")); dlsym(m_wl_module, "wl_egl_window_resize"));
if (!m_wl_egl_window_create || !m_wl_egl_window_destroy || !m_wl_egl_window_resize) if (!m_wl_egl_window_create || !m_wl_egl_window_destroy || !m_wl_egl_window_resize) {
{
Log_ErrorPrintf("Failed to load one or more functions from %s.", WAYLAND_EGL_MODNAME); Log_ErrorPrintf("Failed to load one or more functions from %s.", WAYLAND_EGL_MODNAME);
return false; return false;
} }

View file

@ -1,11 +1,10 @@
#pragma once #pragma once
#include "context_egl.h"
#include <wayland-egl.h> #include <wayland-egl.h>
#include "context_egl.h"
namespace GL { namespace GL {
class ContextEGLWayland final : public ContextEGL class ContextEGLWayland final : public ContextEGL {
{
public: public:
ContextEGLWayland(const WindowInfo& wi); ContextEGLWayland(const WindowInfo& wi);
~ContextEGLWayland() override; ~ContextEGLWayland() override;
@ -27,7 +26,8 @@ private:
void* m_wl_module = nullptr; void* m_wl_module = nullptr;
wl_egl_window* (*m_wl_egl_window_create)(struct wl_surface* surface, int width, int height); wl_egl_window* (*m_wl_egl_window_create)(struct wl_surface* surface, int width, int height);
void (*m_wl_egl_window_destroy)(struct wl_egl_window* egl_window); void (*m_wl_egl_window_destroy)(struct wl_egl_window* egl_window);
void (*m_wl_egl_window_resize)(struct wl_egl_window* egl_window, int width, int height, int dx, int dy); void (*m_wl_egl_window_resize)(struct wl_egl_window* egl_window, int width, int height, int dx,
int dy);
}; };
} // namespace GL } // namespace GL

View file

@ -1,5 +1,5 @@
#include "context_egl_x11.h"
#include "../log.h" #include "../log.h"
#include "context_egl_x11.h"
Log_SetChannel(GL::ContextEGLX11); Log_SetChannel(GL::ContextEGLX11);
namespace GL { namespace GL {
@ -7,8 +7,7 @@ ContextEGLX11::ContextEGLX11(const WindowInfo& wi) : ContextEGL(wi) {}
ContextEGLX11::~ContextEGLX11() = default; ContextEGLX11::~ContextEGLX11() = default;
std::unique_ptr<Context> ContextEGLX11::Create(const WindowInfo& wi, const Version* versions_to_try, std::unique_ptr<Context> ContextEGLX11::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try) size_t num_versions_to_try) {
{
std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi); std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi);
if (!context->Initialize(versions_to_try, num_versions_to_try)) if (!context->Initialize(versions_to_try, num_versions_to_try))
return nullptr; return nullptr;
@ -16,8 +15,7 @@ std::unique_ptr<Context> ContextEGLX11::Create(const WindowInfo& wi, const Versi
return context; return context;
} }
std::unique_ptr<Context> ContextEGLX11::CreateSharedContext(const WindowInfo& wi) std::unique_ptr<Context> ContextEGLX11::CreateSharedContext(const WindowInfo& wi) {
{
std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi); std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi);
context->m_display = m_display; context->m_display = m_display;
@ -27,19 +25,16 @@ std::unique_ptr<Context> ContextEGLX11::CreateSharedContext(const WindowInfo& wi
return context; return context;
} }
void ContextEGLX11::ResizeSurface(u32 new_surface_width, u32 new_surface_height) void ContextEGLX11::ResizeSurface(u32 new_surface_width, u32 new_surface_height) {
{
m_window.Resize(); m_window.Resize();
ContextEGL::ResizeSurface(new_surface_width, new_surface_height); ContextEGL::ResizeSurface(new_surface_width, new_surface_height);
} }
EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config) EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config) {
{
X11InhibitErrors ei; X11InhibitErrors ei;
EGLint native_visual_id = 0; EGLint native_visual_id = 0;
if (!eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) if (!eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) {
{
Log_ErrorPrintf("Failed to get X11 visual ID"); Log_ErrorPrintf("Failed to get X11 visual ID");
return false; return false;
} }
@ -48,16 +43,17 @@ EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config)
vi_query.visualid = native_visual_id; vi_query.visualid = native_visual_id;
int num_vis; int num_vis;
XVisualInfo* vi = XGetVisualInfo(static_cast<Display*>(m_wi.display_connection), VisualIDMask, &vi_query, &num_vis); XVisualInfo* vi = XGetVisualInfo(static_cast<Display*>(m_wi.display_connection), VisualIDMask,
if (num_vis <= 0 || !vi) &vi_query, &num_vis);
{ if (num_vis <= 0 || !vi) {
Log_ErrorPrintf("Failed to query visual from X11"); Log_ErrorPrintf("Failed to query visual from X11");
return false; return false;
} }
m_window.Destroy(); m_window.Destroy();
if (!m_window.Create(GetDisplay(), static_cast<Window>(reinterpret_cast<uintptr_t>(m_wi.window_handle)), vi)) if (!m_window.Create(GetDisplay(),
{ static_cast<Window>(reinterpret_cast<uintptr_t>(m_wi.window_handle)),
vi)) {
Log_ErrorPrintf("Faild to create X11 child window"); Log_ErrorPrintf("Faild to create X11 child window");
XFree(vi); XFree(vi);
return false; return false;

View file

@ -4,8 +4,7 @@
namespace GL { namespace GL {
class ContextEGLX11 final : public ContextEGL class ContextEGLX11 final : public ContextEGL {
{
public: public:
ContextEGLX11(const WindowInfo& wi); ContextEGLX11(const WindowInfo& wi);
~ContextEGLX11() override; ~ContextEGLX11() override;
@ -20,7 +19,9 @@ protected:
EGLNativeWindowType GetNativeWindow(EGLConfig config) override; EGLNativeWindowType GetNativeWindow(EGLConfig config) override;
private: private:
ALWAYS_INLINE Display* GetDisplay() const { return static_cast<Display*>(m_wi.display_connection); } ALWAYS_INLINE Display* GetDisplay() const {
return static_cast<Display*>(m_wi.display_connection);
}
X11Window m_window; X11Window m_window;
}; };

View file

@ -1,14 +1,13 @@
#include "context_glx.h" #include <dlfcn.h>
#include "../duckstation_compat.h" #include "../duckstation_compat.h"
#include "../log.h" #include "../log.h"
#include <dlfcn.h> #include "context_glx.h"
Log_SetChannel(GL::ContextGLX); Log_SetChannel(GL::ContextGLX);
namespace GL { namespace GL {
ContextGLX::ContextGLX(const WindowInfo& wi) : Context(wi) {} ContextGLX::ContextGLX(const WindowInfo& wi) : Context(wi) {}
ContextGLX::~ContextGLX() ContextGLX::~ContextGLX() {
{
if (glXGetCurrentContext() == m_context) if (glXGetCurrentContext() == m_context)
glXMakeCurrent(GetDisplay(), None, nullptr); glXMakeCurrent(GetDisplay(), None, nullptr);
@ -23,8 +22,7 @@ ContextGLX::~ContextGLX()
} }
std::unique_ptr<Context> ContextGLX::Create(const WindowInfo& wi, const Version* versions_to_try, std::unique_ptr<Context> ContextGLX::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try) size_t num_versions_to_try) {
{
std::unique_ptr<ContextGLX> context = std::make_unique<ContextGLX>(wi); std::unique_ptr<ContextGLX> context = std::make_unique<ContextGLX>(wi);
if (!context->Initialize(versions_to_try, num_versions_to_try)) if (!context->Initialize(versions_to_try, num_versions_to_try))
return nullptr; return nullptr;
@ -32,47 +30,36 @@ std::unique_ptr<Context> ContextGLX::Create(const WindowInfo& wi, const Version*
return context; return context;
} }
bool ContextGLX::Initialize(const Version* versions_to_try, size_t num_versions_to_try) bool ContextGLX::Initialize(const Version* versions_to_try, size_t num_versions_to_try) {
{
// We need libGL loaded, because GLAD loads its own, then releases it. // We need libGL loaded, because GLAD loads its own, then releases it.
m_libGL_handle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL); m_libGL_handle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL);
if (!m_libGL_handle) if (!m_libGL_handle) {
{
m_libGL_handle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL); m_libGL_handle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL);
if (!m_libGL_handle) if (!m_libGL_handle) {
{
Log_ErrorPrintf("Failed to load libGL.so: %s", dlerror()); Log_ErrorPrintf("Failed to load libGL.so: %s", dlerror());
return false; return false;
} }
} }
const int screen = DefaultScreen(GetDisplay()); const int screen = DefaultScreen(GetDisplay());
if (!gladLoadGLX(GetDisplay(), screen)) if (!gladLoadGLX(GetDisplay(), screen)) {
{
Log_ErrorPrintf("Loading GLAD GLX functions failed"); Log_ErrorPrintf("Loading GLAD GLX functions failed");
return false; return false;
} }
if (m_wi.type == WindowInfo::Type::X11) if (m_wi.type == WindowInfo::Type::X11) {
{
if (!CreateWindow(screen)) if (!CreateWindow(screen))
return false; return false;
} } else {
else
{
Panic("Create pbuffer"); Panic("Create pbuffer");
} }
for (size_t i = 0; i < num_versions_to_try; i++) for (size_t i = 0; i < num_versions_to_try; i++) {
{
const Version& cv = versions_to_try[i]; const Version& cv = versions_to_try[i];
if (cv.profile == Profile::NoProfile && CreateAnyContext(nullptr, true)) if (cv.profile == Profile::NoProfile && CreateAnyContext(nullptr, true)) {
{
m_version = cv; m_version = cv;
return true; return true;
} } else if (cv.profile != Profile::NoProfile && CreateVersionContext(cv, nullptr, true)) {
else if (cv.profile != Profile::NoProfile && CreateVersionContext(cv, nullptr, true))
{
m_version = cv; m_version = cv;
return true; return true;
} }
@ -81,13 +68,11 @@ bool ContextGLX::Initialize(const Version* versions_to_try, size_t num_versions_
return false; return false;
} }
void* ContextGLX::GetProcAddress(const char* name) void* ContextGLX::GetProcAddress(const char* name) {
{
return reinterpret_cast<void*>(glXGetProcAddress(reinterpret_cast<const GLubyte*>(name))); return reinterpret_cast<void*>(glXGetProcAddress(reinterpret_cast<const GLubyte*>(name)));
} }
bool ContextGLX::ChangeSurface(const WindowInfo& new_wi) bool ContextGLX::ChangeSurface(const WindowInfo& new_wi) {
{
const bool was_current = (glXGetCurrentContext() == m_context); const bool was_current = (glXGetCurrentContext() == m_context);
if (was_current) if (was_current)
glXMakeCurrent(GetDisplay(), None, nullptr); glXMakeCurrent(GetDisplay(), None, nullptr);
@ -95,15 +80,13 @@ bool ContextGLX::ChangeSurface(const WindowInfo& new_wi)
m_window.Destroy(); m_window.Destroy();
m_wi = new_wi; m_wi = new_wi;
if (new_wi.type == WindowInfo::Type::X11) if (new_wi.type == WindowInfo::Type::X11) {
{
const int screen = DefaultScreen(GetDisplay()); const int screen = DefaultScreen(GetDisplay());
if (!CreateWindow(screen)) if (!CreateWindow(screen))
return false; return false;
} }
if (was_current && !glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) if (was_current && !glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) {
{
Log_ErrorPrintf("Failed to make context current again after surface change"); Log_ErrorPrintf("Failed to make context current again after surface change");
return false; return false;
} }
@ -111,71 +94,52 @@ bool ContextGLX::ChangeSurface(const WindowInfo& new_wi)
return true; return true;
} }
void ContextGLX::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) void ContextGLX::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) {
{
m_window.Resize(new_surface_width, new_surface_height); m_window.Resize(new_surface_width, new_surface_height);
m_wi.surface_width = m_window.GetWidth(); m_wi.surface_width = m_window.GetWidth();
m_wi.surface_height = m_window.GetHeight(); m_wi.surface_height = m_window.GetHeight();
} }
bool ContextGLX::SwapBuffers() bool ContextGLX::SwapBuffers() {
{
glXSwapBuffers(GetDisplay(), GetDrawable()); glXSwapBuffers(GetDisplay(), GetDrawable());
return true; return true;
} }
bool ContextGLX::MakeCurrent() bool ContextGLX::MakeCurrent() {
{
return (glXMakeCurrent(GetDisplay(), GetDrawable(), m_context) == True); return (glXMakeCurrent(GetDisplay(), GetDrawable(), m_context) == True);
} }
bool ContextGLX::DoneCurrent() bool ContextGLX::DoneCurrent() {
{
return (glXMakeCurrent(GetDisplay(), None, nullptr) == True); return (glXMakeCurrent(GetDisplay(), None, nullptr) == True);
} }
bool ContextGLX::SetSwapInterval(s32 interval) bool ContextGLX::SetSwapInterval(s32 interval) {
{ if (GLAD_GLX_EXT_swap_control) {
if (GLAD_GLX_EXT_swap_control)
{
glXSwapIntervalEXT(GetDisplay(), GetDrawable(), interval); glXSwapIntervalEXT(GetDisplay(), GetDrawable(), interval);
return true; return true;
} } else if (GLAD_GLX_MESA_swap_control) {
else if (GLAD_GLX_MESA_swap_control)
{
return (glXSwapIntervalMESA(static_cast<u32>(std::max(interval, 0))) != 0); return (glXSwapIntervalMESA(static_cast<u32>(std::max(interval, 0))) != 0);
} } else if (GLAD_GLX_SGI_swap_control) {
else if (GLAD_GLX_SGI_swap_control)
{
return (glXSwapIntervalSGI(interval) != 0); return (glXSwapIntervalSGI(interval) != 0);
} } else {
else
{
return false; return false;
} }
} }
std::unique_ptr<Context> ContextGLX::CreateSharedContext(const WindowInfo& wi) std::unique_ptr<Context> ContextGLX::CreateSharedContext(const WindowInfo& wi) {
{
std::unique_ptr<ContextGLX> context = std::make_unique<ContextGLX>(wi); std::unique_ptr<ContextGLX> context = std::make_unique<ContextGLX>(wi);
if (wi.type == WindowInfo::Type::X11) if (wi.type == WindowInfo::Type::X11) {
{
const int screen = DefaultScreen(context->GetDisplay()); const int screen = DefaultScreen(context->GetDisplay());
if (!context->CreateWindow(screen)) if (!context->CreateWindow(screen))
return nullptr; return nullptr;
} } else {
else
{
Panic("Create pbuffer"); Panic("Create pbuffer");
} }
if (m_version.profile == Profile::NoProfile) if (m_version.profile == Profile::NoProfile) {
{
if (!context->CreateAnyContext(m_context, false)) if (!context->CreateAnyContext(m_context, false))
return nullptr; return nullptr;
} } else {
else
{
if (!context->CreateVersionContext(m_version, m_context, false)) if (!context->CreateVersionContext(m_version, m_context, false))
return nullptr; return nullptr;
} }
@ -184,14 +148,12 @@ std::unique_ptr<Context> ContextGLX::CreateSharedContext(const WindowInfo& wi)
return context; return context;
} }
bool ContextGLX::CreateWindow(int screen) bool ContextGLX::CreateWindow(int screen) {
{
int attribs[32] = {GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, int attribs[32] = {GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_DOUBLEBUFFER, True}; GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_DOUBLEBUFFER, True};
int nattribs = 8; int nattribs = 8;
switch (m_wi.surface_format) switch (m_wi.surface_format) {
{
case WindowInfo::SurfaceFormat::RGB8: case WindowInfo::SurfaceFormat::RGB8:
attribs[nattribs++] = GLX_RED_SIZE; attribs[nattribs++] = GLX_RED_SIZE;
attribs[nattribs++] = 8; attribs[nattribs++] = 8;
@ -234,45 +196,39 @@ bool ContextGLX::CreateWindow(int screen)
int fbcount = 0; int fbcount = 0;
GLXFBConfig* fbc = glXChooseFBConfig(GetDisplay(), screen, attribs, &fbcount); GLXFBConfig* fbc = glXChooseFBConfig(GetDisplay(), screen, attribs, &fbcount);
if (!fbc || !fbcount) if (!fbc || !fbcount) {
{
Log_ErrorPrintf("glXChooseFBConfig() failed"); Log_ErrorPrintf("glXChooseFBConfig() failed");
return false; return false;
} }
m_fb_config = *fbc; m_fb_config = *fbc;
XFree(fbc); XFree(fbc);
if (!GLAD_GLX_VERSION_1_3) if (!GLAD_GLX_VERSION_1_3) {
{
Log_ErrorPrintf("GLX Version 1.3 is required"); Log_ErrorPrintf("GLX Version 1.3 is required");
return false; return false;
} }
m_vi = glXGetVisualFromFBConfig(GetDisplay(), m_fb_config); m_vi = glXGetVisualFromFBConfig(GetDisplay(), m_fb_config);
if (!m_vi) if (!m_vi) {
{
Log_ErrorPrintf("glXGetVisualFromFBConfig() failed"); Log_ErrorPrintf("glXGetVisualFromFBConfig() failed");
return false; return false;
} }
return m_window.Create(GetDisplay(), static_cast<Window>(reinterpret_cast<uintptr_t>(m_wi.window_handle)), m_vi); return m_window.Create(
GetDisplay(), static_cast<Window>(reinterpret_cast<uintptr_t>(m_wi.window_handle)), m_vi);
} }
bool ContextGLX::CreateAnyContext(GLXContext share_context, bool make_current) bool ContextGLX::CreateAnyContext(GLXContext share_context, bool make_current) {
{
X11InhibitErrors ie; X11InhibitErrors ie;
m_context = glXCreateContext(GetDisplay(), m_vi, share_context, True); m_context = glXCreateContext(GetDisplay(), m_vi, share_context, True);
if (!m_context || ie.HadError()) if (!m_context || ie.HadError()) {
{
Log_ErrorPrintf("glxCreateContext() failed"); Log_ErrorPrintf("glxCreateContext() failed");
return false; return false;
} }
if (make_current) if (make_current) {
{ if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) {
if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context))
{
Log_ErrorPrintf("glXMakeCurrent() failed"); Log_ErrorPrintf("glXMakeCurrent() failed");
return false; return false;
} }
@ -281,11 +237,10 @@ bool ContextGLX::CreateAnyContext(GLXContext share_context, bool make_current)
return true; return true;
} }
bool ContextGLX::CreateVersionContext(const Version& version, GLXContext share_context, bool make_current) bool ContextGLX::CreateVersionContext(const Version& version, GLXContext share_context,
{ bool make_current) {
// we need create context attribs // we need create context attribs
if (!GLAD_GLX_VERSION_1_3) if (!GLAD_GLX_VERSION_1_3) {
{
Log_ErrorPrint("Missing GLX version 1.3."); Log_ErrorPrint("Missing GLX version 1.3.");
return false; return false;
} }
@ -293,10 +248,10 @@ bool ContextGLX::CreateVersionContext(const Version& version, GLXContext share_c
int attribs[32]; int attribs[32];
int nattribs = 0; int nattribs = 0;
attribs[nattribs++] = GLX_CONTEXT_PROFILE_MASK_ARB; attribs[nattribs++] = GLX_CONTEXT_PROFILE_MASK_ARB;
attribs[nattribs++] = attribs[nattribs++] = ((version.profile == Profile::ES)
((version.profile == Profile::ES) ? ? ((version.major_version >= 2) ? GLX_CONTEXT_ES2_PROFILE_BIT_EXT
((version.major_version >= 2) ? GLX_CONTEXT_ES2_PROFILE_BIT_EXT : GLX_CONTEXT_ES_PROFILE_BIT_EXT) : : GLX_CONTEXT_ES_PROFILE_BIT_EXT)
GLX_CONTEXT_CORE_PROFILE_BIT_ARB); : GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
attribs[nattribs++] = GLX_CONTEXT_MAJOR_VERSION_ARB; attribs[nattribs++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
attribs[nattribs++] = version.major_version; attribs[nattribs++] = version.major_version;
attribs[nattribs++] = GLX_CONTEXT_MINOR_VERSION_ARB; attribs[nattribs++] = GLX_CONTEXT_MINOR_VERSION_ARB;
@ -312,10 +267,8 @@ bool ContextGLX::CreateVersionContext(const Version& version, GLXContext share_c
if (!m_context) if (!m_context)
return false; return false;
if (make_current) if (make_current) {
{ if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) {
if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context))
{
Log_ErrorPrint("glXMakeCurrent() failed"); Log_ErrorPrint("glXMakeCurrent() failed");
glXDestroyContext(GetDisplay(), m_context); glXDestroyContext(GetDisplay(), m_context);
m_context = nullptr; m_context = nullptr;

View file

@ -1,12 +1,11 @@
#pragma once #pragma once
#include "context.h"
#include "../../../../../externals/glad/src/glad_glx.h" #include "../../../../../externals/glad/src/glad_glx.h"
#include "context.h"
#include "x11_window.h" #include "x11_window.h"
namespace GL { namespace GL {
class ContextGLX final : public Context class ContextGLX final : public Context {
{
public: public:
ContextGLX(const WindowInfo& wi); ContextGLX(const WindowInfo& wi);
~ContextGLX() override; ~ContextGLX() override;
@ -24,8 +23,12 @@ public:
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override; std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
private: private:
ALWAYS_INLINE Display* GetDisplay() const { return static_cast<Display*>(m_wi.display_connection); } ALWAYS_INLINE Display* GetDisplay() const {
ALWAYS_INLINE GLXDrawable GetDrawable() const { return static_cast<GLXDrawable>(m_window.GetWindow()); } return static_cast<Display*>(m_wi.display_connection);
}
ALWAYS_INLINE GLXDrawable GetDrawable() const {
return static_cast<GLXDrawable>(m_window.GetWindow());
}
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
bool CreateWindow(int screen); bool CreateWindow(int screen);

View file

@ -1,7 +1,7 @@
#include "context_wgl.h"
#include "../duckstation_compat.h" #include "../duckstation_compat.h"
#include "../log.h" #include "../log.h"
#include "../scoped_guard.h" #include "../scoped_guard.h"
#include "context_wgl.h"
#include "loader.h" #include "loader.h"
using namespace melonDS; using namespace melonDS;
Log_SetChannel(GL::ContextWGL); Log_SetChannel(GL::ContextWGL);
@ -9,8 +9,7 @@ Log_SetChannel(GL::ContextWGL);
// TODO: get rid of this // TODO: get rid of this
#pragma comment(lib, "opengl32.lib") #pragma comment(lib, "opengl32.lib")
static void* GetProcAddressCallback(const char* name) static void* GetProcAddressCallback(const char* name) {
{
void* addr = reinterpret_cast<void*>(wglGetProcAddress(name)); void* addr = reinterpret_cast<void*>(wglGetProcAddress(name));
if (addr) if (addr)
return addr; return addr;
@ -22,8 +21,7 @@ static void* GetProcAddressCallback(const char* name)
namespace GL { namespace GL {
ContextWGL::ContextWGL(const WindowInfo& wi) : Context(wi) {} ContextWGL::ContextWGL(const WindowInfo& wi) : Context(wi) {}
ContextWGL::~ContextWGL() ContextWGL::~ContextWGL() {
{
if (wglGetCurrentContext() == m_rc) if (wglGetCurrentContext() == m_rc)
wglMakeCurrent(m_dc, nullptr); wglMakeCurrent(m_dc, nullptr);
@ -34,8 +32,7 @@ ContextWGL::~ContextWGL()
} }
std::unique_ptr<Context> ContextWGL::Create(const WindowInfo& wi, const Version* versions_to_try, std::unique_ptr<Context> ContextWGL::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try) size_t num_versions_to_try) {
{
std::unique_ptr<ContextWGL> context = std::make_unique<ContextWGL>(wi); std::unique_ptr<ContextWGL> context = std::make_unique<ContextWGL>(wi);
if (!context->Initialize(versions_to_try, num_versions_to_try)) if (!context->Initialize(versions_to_try, num_versions_to_try))
return nullptr; return nullptr;
@ -43,15 +40,11 @@ std::unique_ptr<Context> ContextWGL::Create(const WindowInfo& wi, const Version*
return context; return context;
} }
bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) {
{ if (m_wi.type == WindowInfo::Type::Win32) {
if (m_wi.type == WindowInfo::Type::Win32)
{
if (!InitializeDC()) if (!InitializeDC())
return false; return false;
} } else {
else
{
Log_ErrorPrint("ContextWGL must always start with a valid surface."); Log_ErrorPrint("ContextWGL must always start with a valid surface.");
return false; return false;
} }
@ -60,17 +53,13 @@ bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_
if (!CreateAnyContext(nullptr, true)) if (!CreateAnyContext(nullptr, true))
return false; return false;
for (size_t i = 0; i < num_versions_to_try; i++) for (size_t i = 0; i < num_versions_to_try; i++) {
{
const Version& cv = versions_to_try[i]; const Version& cv = versions_to_try[i];
if (cv.profile == Profile::NoProfile) if (cv.profile == Profile::NoProfile) {
{
// we already have the dummy context, so just use that // we already have the dummy context, so just use that
m_version = cv; m_version = cv;
return true; return true;
} } else if (CreateVersionContext(cv, nullptr, true)) {
else if (CreateVersionContext(cv, nullptr, true))
{
m_version = cv; m_version = cv;
return true; return true;
} }
@ -79,13 +68,11 @@ bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_
return false; return false;
} }
void* ContextWGL::GetProcAddress(const char* name) void* ContextWGL::GetProcAddress(const char* name) {
{
return GetProcAddressCallback(name); return GetProcAddressCallback(name);
} }
bool ContextWGL::ChangeSurface(const WindowInfo& new_wi) bool ContextWGL::ChangeSurface(const WindowInfo& new_wi) {
{
const bool was_current = (wglGetCurrentContext() == m_rc); const bool was_current = (wglGetCurrentContext() == m_rc);
ReleaseDC(); ReleaseDC();
@ -94,32 +81,28 @@ bool ContextWGL::ChangeSurface(const WindowInfo& new_wi)
if (!InitializeDC()) if (!InitializeDC())
return false; return false;
if (was_current && !wglMakeCurrent(m_dc, m_rc)) if (was_current && !wglMakeCurrent(m_dc, m_rc)) {
{ Log_ErrorPrintf("Failed to make context current again after surface change: 0x%08X",
Log_ErrorPrintf("Failed to make context current again after surface change: 0x%08X", GetLastError()); GetLastError());
return false; return false;
} }
return true; return true;
} }
void ContextWGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) void ContextWGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) {
{
RECT client_rc = {}; RECT client_rc = {};
GetClientRect(GetHWND(), &client_rc); GetClientRect(GetHWND(), &client_rc);
m_wi.surface_width = static_cast<u32>(client_rc.right - client_rc.left); m_wi.surface_width = static_cast<u32>(client_rc.right - client_rc.left);
m_wi.surface_height = static_cast<u32>(client_rc.bottom - client_rc.top); m_wi.surface_height = static_cast<u32>(client_rc.bottom - client_rc.top);
} }
bool ContextWGL::SwapBuffers() bool ContextWGL::SwapBuffers() {
{
return ::SwapBuffers(m_dc); return ::SwapBuffers(m_dc);
} }
bool ContextWGL::MakeCurrent() bool ContextWGL::MakeCurrent() {
{ if (!wglMakeCurrent(m_dc, m_rc)) {
if (!wglMakeCurrent(m_dc, m_rc))
{
Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError());
return false; return false;
} }
@ -127,40 +110,31 @@ bool ContextWGL::MakeCurrent()
return true; return true;
} }
bool ContextWGL::DoneCurrent() bool ContextWGL::DoneCurrent() {
{
return wglMakeCurrent(m_dc, nullptr); return wglMakeCurrent(m_dc, nullptr);
} }
bool ContextWGL::SetSwapInterval(s32 interval) bool ContextWGL::SetSwapInterval(s32 interval) {
{
if (!GLAD_WGL_EXT_swap_control) if (!GLAD_WGL_EXT_swap_control)
return false; return false;
return wglSwapIntervalEXT(interval); return wglSwapIntervalEXT(interval);
} }
std::unique_ptr<Context> ContextWGL::CreateSharedContext(const WindowInfo& wi) std::unique_ptr<Context> ContextWGL::CreateSharedContext(const WindowInfo& wi) {
{
std::unique_ptr<ContextWGL> context = std::make_unique<ContextWGL>(wi); std::unique_ptr<ContextWGL> context = std::make_unique<ContextWGL>(wi);
if (wi.type == WindowInfo::Type::Win32) if (wi.type == WindowInfo::Type::Win32) {
{
if (!context->InitializeDC()) if (!context->InitializeDC())
return nullptr; return nullptr;
} } else {
else
{
Log_ErrorPrint("PBuffer not implemented"); Log_ErrorPrint("PBuffer not implemented");
return nullptr; return nullptr;
} }
if (m_version.profile == Profile::NoProfile) if (m_version.profile == Profile::NoProfile) {
{
if (!context->CreateAnyContext(m_rc, false)) if (!context->CreateAnyContext(m_rc, false))
return nullptr; return nullptr;
} } else {
else
{
if (!context->CreateVersionContext(m_version, m_rc, false)) if (!context->CreateVersionContext(m_version, m_rc, false))
return nullptr; return nullptr;
} }
@ -169,8 +143,7 @@ std::unique_ptr<Context> ContextWGL::CreateSharedContext(const WindowInfo& wi)
return context; return context;
} }
HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd) HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd) {
{
PIXELFORMATDESCRIPTOR pfd = {}; PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(pfd); pfd.nSize = sizeof(pfd);
pfd.nVersion = 1; pfd.nVersion = 1;
@ -183,17 +156,14 @@ HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd)
pfd.cColorBits = 24; pfd.cColorBits = 24;
HDC hDC = ::GetDC(hwnd); HDC hDC = ::GetDC(hwnd);
if (!hDC) if (!hDC) {
{
Log_ErrorPrintf("GetDC() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("GetDC() failed: 0x%08X", GetLastError());
return {}; return {};
} }
if (!m_pixel_format.has_value()) if (!m_pixel_format.has_value()) {
{
const int pf = ChoosePixelFormat(hDC, &pfd); const int pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0) if (pf == 0) {
{
Log_ErrorPrintf("ChoosePixelFormat() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("ChoosePixelFormat() failed: 0x%08X", GetLastError());
::ReleaseDC(hwnd, hDC); ::ReleaseDC(hwnd, hDC);
return {}; return {};
@ -202,8 +172,7 @@ HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd)
m_pixel_format = pf; m_pixel_format = pf;
} }
if (!SetPixelFormat(hDC, m_pixel_format.value(), &pfd)) if (!SetPixelFormat(hDC, m_pixel_format.value(), &pfd)) {
{
Log_ErrorPrintf("SetPixelFormat() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("SetPixelFormat() failed: 0x%08X", GetLastError());
::ReleaseDC(hwnd, hDC); ::ReleaseDC(hwnd, hDC);
return {}; return {};
@ -212,34 +181,25 @@ HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd)
return hDC; return hDC;
} }
bool ContextWGL::InitializeDC() bool ContextWGL::InitializeDC() {
{ if (m_wi.type == WindowInfo::Type::Win32) {
if (m_wi.type == WindowInfo::Type::Win32)
{
m_dc = GetDCAndSetPixelFormat(GetHWND()); m_dc = GetDCAndSetPixelFormat(GetHWND());
if (!m_dc) if (!m_dc) {
{
Log_ErrorPrint("Failed to get DC for window"); Log_ErrorPrint("Failed to get DC for window");
return false; return false;
} }
return true; return true;
} } else if (m_wi.type == WindowInfo::Type::Surfaceless) {
else if (m_wi.type == WindowInfo::Type::Surfaceless)
{
return CreatePBuffer(); return CreatePBuffer();
} } else {
else
{
Log_ErrorPrintf("Unknown window info type %u", static_cast<unsigned>(m_wi.type)); Log_ErrorPrintf("Unknown window info type %u", static_cast<unsigned>(m_wi.type));
return false; return false;
} }
} }
void ContextWGL::ReleaseDC() void ContextWGL::ReleaseDC() {
{ if (m_pbuffer) {
if (m_pbuffer)
{
wglReleasePbufferDCARB(m_pbuffer, m_dc); wglReleasePbufferDCARB(m_pbuffer, m_dc);
m_dc = {}; m_dc = {};
@ -251,21 +211,17 @@ void ContextWGL::ReleaseDC()
DestroyWindow(m_dummy_window); DestroyWindow(m_dummy_window);
m_dummy_window = {}; m_dummy_window = {};
} } else if (m_dc) {
else if (m_dc)
{
::ReleaseDC(GetHWND(), m_dc); ::ReleaseDC(GetHWND(), m_dc);
m_dc = {}; m_dc = {};
} }
} }
bool ContextWGL::CreatePBuffer() bool ContextWGL::CreatePBuffer() {
{
static bool window_class_registered = false; static bool window_class_registered = false;
static const wchar_t* window_class_name = L"ContextWGLPBuffer"; static const wchar_t* window_class_name = L"ContextWGLPBuffer";
if (!window_class_registered) if (!window_class_registered) {
{
WNDCLASSEXW wc = {}; WNDCLASSEXW wc = {};
wc.cbSize = sizeof(WNDCLASSEXW); wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = 0; wc.style = 0;
@ -280,8 +236,7 @@ bool ContextWGL::CreatePBuffer()
wc.lpszClassName = window_class_name; wc.lpszClassName = window_class_name;
wc.hIconSm = NULL; wc.hIconSm = NULL;
if (!RegisterClassExW(&wc)) if (!RegisterClassExW(&wc)) {
{
Log_ErrorPrint("(ContextWGL::CreatePBuffer) RegisterClassExW() failed"); Log_ErrorPrint("(ContextWGL::CreatePBuffer) RegisterClassExW() failed");
return false; return false;
} }
@ -289,9 +244,9 @@ bool ContextWGL::CreatePBuffer()
window_class_registered = true; window_class_registered = true;
} }
HWND hwnd = CreateWindowExW(0, window_class_name, window_class_name, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); HWND hwnd = CreateWindowExW(0, window_class_name, window_class_name, 0, 0, 0, 0, 0, NULL, NULL,
if (!hwnd) NULL, NULL);
{ if (!hwnd) {
Log_ErrorPrint("(ContextWGL::CreatePBuffer) CreateWindowEx() failed"); Log_ErrorPrint("(ContextWGL::CreatePBuffer) CreateWindowEx() failed");
return false; return false;
} }
@ -308,8 +263,7 @@ bool ContextWGL::CreatePBuffer()
AssertMsg(m_pixel_format.has_value(), "Has pixel format for pbuffer"); AssertMsg(m_pixel_format.has_value(), "Has pixel format for pbuffer");
HPBUFFERARB pbuffer = wglCreatePbufferARB(hdc, m_pixel_format.value(), 1, 1, pb_attribs); HPBUFFERARB pbuffer = wglCreatePbufferARB(hdc, m_pixel_format.value(), 1, 1, pb_attribs);
if (!pbuffer) if (!pbuffer) {
{
Log_ErrorPrint("(ContextWGL::CreatePBuffer) wglCreatePbufferARB() failed"); Log_ErrorPrint("(ContextWGL::CreatePBuffer) wglCreatePbufferARB() failed");
return false; return false;
} }
@ -317,8 +271,7 @@ bool ContextWGL::CreatePBuffer()
ScopedGuard pbuffer_guard([pbuffer]() { wglDestroyPbufferARB(pbuffer); }); ScopedGuard pbuffer_guard([pbuffer]() { wglDestroyPbufferARB(pbuffer); });
m_dc = wglGetPbufferDCARB(pbuffer); m_dc = wglGetPbufferDCARB(pbuffer);
if (!m_dc) if (!m_dc) {
{
Log_ErrorPrint("(ContextWGL::CreatePbuffer) wglGetPbufferDCARB() failed"); Log_ErrorPrint("(ContextWGL::CreatePbuffer) wglGetPbufferDCARB() failed");
return false; return false;
} }
@ -333,33 +286,31 @@ bool ContextWGL::CreatePBuffer()
return true; return true;
} }
bool ContextWGL::CreateAnyContext(HGLRC share_context, bool make_current) bool ContextWGL::CreateAnyContext(HGLRC share_context, bool make_current) {
{
m_rc = wglCreateContext(m_dc); m_rc = wglCreateContext(m_dc);
if (!m_rc) if (!m_rc) {
{
Log_ErrorPrintf("wglCreateContext() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("wglCreateContext() failed: 0x%08X", GetLastError());
return false; return false;
} }
if (make_current) if (make_current) {
{ if (!wglMakeCurrent(m_dc, m_rc)) {
if (!wglMakeCurrent(m_dc, m_rc))
{
Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError());
return false; return false;
} }
// re-init glad-wgl // re-init glad-wgl
if (!gladLoadWGLLoader([](const char* name) -> void* { return reinterpret_cast<void*>(wglGetProcAddress(name)); }, m_dc)) if (!gladLoadWGLLoader(
{ [](const char* name) -> void* {
return reinterpret_cast<void*>(wglGetProcAddress(name));
},
m_dc)) {
Log_ErrorPrint("Loading GLAD WGL functions failed"); Log_ErrorPrint("Loading GLAD WGL functions failed");
return false; return false;
} }
} }
if (share_context && !wglShareLists(share_context, m_rc)) if (share_context && !wglShareLists(share_context, m_rc)) {
{
Log_ErrorPrintf("wglShareLists() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("wglShareLists() failed: 0x%08X", GetLastError());
return false; return false;
} }
@ -367,18 +318,16 @@ bool ContextWGL::CreateAnyContext(HGLRC share_context, bool make_current)
return true; return true;
} }
bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_context, bool make_current) bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_context,
{ bool make_current) {
// we need create context attribs // we need create context attribs
if (!GLAD_WGL_ARB_create_context) if (!GLAD_WGL_ARB_create_context) {
{
Log_ErrorPrint("Missing GLAD_WGL_ARB_create_context."); Log_ErrorPrint("Missing GLAD_WGL_ARB_create_context.");
return false; return false;
} }
HGLRC new_rc; HGLRC new_rc;
if (version.profile == Profile::Core) if (version.profile == Profile::Core) {
{
const int attribs[] = {WGL_CONTEXT_PROFILE_MASK_ARB, const int attribs[] = {WGL_CONTEXT_PROFILE_MASK_ARB,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
WGL_CONTEXT_MAJOR_VERSION_ARB, WGL_CONTEXT_MAJOR_VERSION_ARB,
@ -396,19 +345,16 @@ bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_contex
0}; 0};
new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs); new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs);
} } else if (version.profile == Profile::ES) {
else if (version.profile == Profile::ES)
{
if ((version.major_version >= 2 && !GLAD_WGL_EXT_create_context_es2_profile) || if ((version.major_version >= 2 && !GLAD_WGL_EXT_create_context_es2_profile) ||
(version.major_version < 2 && !GLAD_WGL_EXT_create_context_es_profile)) (version.major_version < 2 && !GLAD_WGL_EXT_create_context_es_profile)) {
{
Log_ErrorPrint("WGL_EXT_create_context_es_profile not supported"); Log_ErrorPrint("WGL_EXT_create_context_es_profile not supported");
return false; return false;
} }
const int attribs[] = { const int attribs[] = {WGL_CONTEXT_PROFILE_MASK_ARB,
WGL_CONTEXT_PROFILE_MASK_ARB, ((version.major_version >= 2) ? WGL_CONTEXT_ES2_PROFILE_BIT_EXT
((version.major_version >= 2) ? WGL_CONTEXT_ES2_PROFILE_BIT_EXT : WGL_CONTEXT_ES_PROFILE_BIT_EXT), : WGL_CONTEXT_ES_PROFILE_BIT_EXT),
WGL_CONTEXT_MAJOR_VERSION_ARB, WGL_CONTEXT_MAJOR_VERSION_ARB,
version.major_version, version.major_version,
WGL_CONTEXT_MINOR_VERSION_ARB, WGL_CONTEXT_MINOR_VERSION_ARB,
@ -417,9 +363,7 @@ bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_contex
0}; 0};
new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs); new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs);
} } else {
else
{
Log_ErrorPrint("Unknown profile"); Log_ErrorPrint("Unknown profile");
return false; return false;
} }
@ -428,18 +372,19 @@ bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_contex
return false; return false;
// destroy and swap contexts // destroy and swap contexts
if (m_rc) if (m_rc) {
{ if (!wglMakeCurrent(m_dc, make_current ? new_rc : nullptr)) {
if (!wglMakeCurrent(m_dc, make_current ? new_rc : nullptr))
{
Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError());
wglDeleteContext(new_rc); wglDeleteContext(new_rc);
return false; return false;
} }
// re-init glad-wgl // re-init glad-wgl
if (make_current && !gladLoadWGLLoader([](const char* name) -> void* { return reinterpret_cast<void*>(wglGetProcAddress(name)); }, m_dc)) if (make_current && !gladLoadWGLLoader(
{ [](const char* name) -> void* {
return reinterpret_cast<void*>(wglGetProcAddress(name));
},
m_dc)) {
Log_ErrorPrint("Loading GLAD WGL functions failed"); Log_ErrorPrint("Loading GLAD WGL functions failed");
return false; return false;
} }

View file

@ -1,15 +1,14 @@
#pragma once #pragma once
#include "../windows_headers.h" #include "../windows_headers.h"
#include "context.h"
#include "../../../../../externals/glad/src/glad_wgl.h"
#include "loader.h"
#include <optional> #include <optional>
#include "../../../../../externals/glad/src/glad_wgl.h"
#include "context.h"
#include "loader.h"
namespace GL { namespace GL {
class ContextWGL final : public Context class ContextWGL final : public Context {
{
public: public:
ContextWGL(const WindowInfo& wi); ContextWGL(const WindowInfo& wi);
~ContextWGL() override; ~ContextWGL() override;
@ -27,7 +26,9 @@ public:
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override; std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
private: private:
ALWAYS_INLINE HWND GetHWND() const { return static_cast<HWND>(m_wi.window_handle); } ALWAYS_INLINE HWND GetHWND() const {
return static_cast<HWND>(m_wi.window_handle);
}
HDC GetDCAndSetPixelFormat(HWND hwnd); HDC GetDCAndSetPixelFormat(HWND hwnd);

View file

@ -1,19 +1,17 @@
#include "x11_window.h"
#include "../log.h"
#include "../duckstation_compat.h"
#include <cstdio> #include <cstdio>
#include "../duckstation_compat.h"
#include "../log.h"
#include "x11_window.h"
Log_SetChannel(X11Window); Log_SetChannel(X11Window);
namespace GL { namespace GL {
X11Window::X11Window() = default; X11Window::X11Window() = default;
X11Window::~X11Window() X11Window::~X11Window() {
{
Destroy(); Destroy();
} }
bool X11Window::Create(Display* display, Window parent_window, const XVisualInfo* vi) bool X11Window::Create(Display* display, Window parent_window, const XVisualInfo* vi) {
{
m_display = display; m_display = display;
m_parent_window = parent_window; m_parent_window = parent_window;
XSync(m_display, True); XSync(m_display, True);
@ -30,39 +28,32 @@ bool X11Window::Create(Display* display, Window parent_window, const XVisualInfo
XSetWindowAttributes wa = {}; XSetWindowAttributes wa = {};
wa.colormap = m_colormap; wa.colormap = m_colormap;
m_window = XCreateWindow(m_display, m_parent_window, 0, 0, m_width, m_height, 0, vi->depth, InputOutput, vi->visual, m_window = XCreateWindow(m_display, m_parent_window, 0, 0, m_width, m_height, 0, vi->depth,
CWColormap, &wa); InputOutput, vi->visual, CWColormap, &wa);
XMapWindow(m_display, m_window); XMapWindow(m_display, m_window);
XSync(m_display, True); XSync(m_display, True);
return true; return true;
} }
void X11Window::Destroy() void X11Window::Destroy() {
{ if (m_window) {
if (m_window)
{
XUnmapWindow(m_display, m_window); XUnmapWindow(m_display, m_window);
XDestroyWindow(m_display, m_window); XDestroyWindow(m_display, m_window);
m_window = {}; m_window = {};
} }
if (m_colormap) if (m_colormap) {
{
XFreeColormap(m_display, m_colormap); XFreeColormap(m_display, m_colormap);
m_colormap = {}; m_colormap = {};
} }
} }
void X11Window::Resize(u32 width, u32 height) void X11Window::Resize(u32 width, u32 height) {
{ if (width != 0 && height != 0) {
if (width != 0 && height != 0)
{
m_width = width; m_width = width;
m_height = height; m_height = height;
} } else {
else
{
XWindowAttributes parent_wa = {}; XWindowAttributes parent_wa = {};
XGetWindowAttributes(m_display, m_parent_window, &parent_wa); XGetWindowAttributes(m_display, m_parent_window, &parent_wa);
m_width = static_cast<u32>(parent_wa.width); m_width = static_cast<u32>(parent_wa.width);
@ -74,26 +65,23 @@ void X11Window::Resize(u32 width, u32 height)
static X11InhibitErrors* s_current_error_inhibiter; static X11InhibitErrors* s_current_error_inhibiter;
X11InhibitErrors::X11InhibitErrors() X11InhibitErrors::X11InhibitErrors() {
{
Assert(!s_current_error_inhibiter); Assert(!s_current_error_inhibiter);
m_old_handler = XSetErrorHandler(ErrorHandler); m_old_handler = XSetErrorHandler(ErrorHandler);
s_current_error_inhibiter = this; s_current_error_inhibiter = this;
} }
X11InhibitErrors::~X11InhibitErrors() X11InhibitErrors::~X11InhibitErrors() {
{
Assert(s_current_error_inhibiter == this); Assert(s_current_error_inhibiter == this);
s_current_error_inhibiter = nullptr; s_current_error_inhibiter = nullptr;
XSetErrorHandler(m_old_handler); XSetErrorHandler(m_old_handler);
} }
int X11InhibitErrors::ErrorHandler(Display* display, XErrorEvent* ee) int X11InhibitErrors::ErrorHandler(Display* display, XErrorEvent* ee) {
{
char error_string[256] = {}; char error_string[256] = {};
XGetErrorText(display, ee->error_code, error_string, sizeof(error_string)); XGetErrorText(display, ee->error_code, error_string, sizeof(error_string));
Log_WarningPrintf("X11 Error: %s (Error %u Minor %u Request %u)", error_string, ee->error_code, ee->minor_code, Log_WarningPrintf("X11 Error: %s (Error %u Minor %u Request %u)", error_string, ee->error_code,
ee->request_code); ee->minor_code, ee->request_code);
s_current_error_inhibiter->m_had_error = true; s_current_error_inhibiter->m_had_error = true;
return 0; return 0;

View file

@ -1,19 +1,24 @@
#pragma once #pragma once
#include "../duckstation_compat.h"
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include "../duckstation_compat.h"
namespace GL { namespace GL {
using namespace citra; using namespace citra;
class X11Window class X11Window {
{
public: public:
X11Window(); X11Window();
~X11Window(); ~X11Window();
ALWAYS_INLINE Window GetWindow() const { return m_window; } ALWAYS_INLINE Window GetWindow() const {
ALWAYS_INLINE u32 GetWidth() const { return m_width; } return m_window;
ALWAYS_INLINE u32 GetHeight() const { return m_height; } }
ALWAYS_INLINE u32 GetWidth() const {
return m_width;
}
ALWAYS_INLINE u32 GetHeight() const {
return m_height;
}
bool Create(Display* display, Window parent_window, const XVisualInfo* vi); bool Create(Display* display, Window parent_window, const XVisualInfo* vi);
void Destroy(); void Destroy();
@ -31,13 +36,14 @@ private:
}; };
// Helper class for managing X errors // Helper class for managing X errors
class X11InhibitErrors class X11InhibitErrors {
{
public: public:
X11InhibitErrors(); X11InhibitErrors();
~X11InhibitErrors(); ~X11InhibitErrors();
ALWAYS_INLINE bool HadError() const { return m_had_error; } ALWAYS_INLINE bool HadError() const {
return m_had_error;
}
private: private:
static int ErrorHandler(Display* display, XErrorEvent* ee); static int ErrorHandler(Display* display, XErrorEvent* ee);

View file

@ -5,41 +5,73 @@
#define Log_SetChannel(ChannelName) #define Log_SetChannel(ChannelName)
#define Log_ErrorPrint(msg) puts(msg "\n"); #define Log_ErrorPrint(msg) puts(msg "\n");
#define Log_ErrorPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_ErrorPrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#define Log_WarningPrint(msg) puts(msg) #define Log_WarningPrint(msg) puts(msg)
#define Log_WarningPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_WarningPrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#define Log_PerfPrint(msg) puts(msg) #define Log_PerfPrint(msg) puts(msg)
#define Log_PerfPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_PerfPrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#define Log_InfoPrint(msg) puts(msg) #define Log_InfoPrint(msg) puts(msg)
#define Log_InfoPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_InfoPrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#define Log_VerbosePrint(msg) puts(msg) #define Log_VerbosePrint(msg) puts(msg)
#define Log_VerbosePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_VerbosePrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#define Log_DevPrint(msg) puts(msg) #define Log_DevPrint(msg) puts(msg)
#define Log_DevPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_DevPrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#define Log_ProfilePrint(msg) puts(msg) #define Log_ProfilePrint(msg) puts(msg)
#define Log_ProfilePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_ProfilePrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#ifdef _DEBUG #ifdef _DEBUG
#define Log_DebugPrint(msg) puts(msg) #define Log_DebugPrint(msg) puts(msg)
#define Log_DebugPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_DebugPrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#define Log_TracePrint(msg) puts(msg) #define Log_TracePrint(msg) puts(msg)
#define Log_TracePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) #define Log_TracePrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#else #else
#define Log_DebugPrint(msg) \ #define Log_DebugPrint(msg) \
do \ do { \
{ \
} while (0) } while (0)
#define Log_DebugPrintf(...) \ #define Log_DebugPrintf(...) \
do \ do { \
{ \
} while (0) } while (0)
#define Log_TracePrint(msg) \ #define Log_TracePrint(msg) \
do \ do { \
{ \
} while (0) } while (0)
#define Log_TracePrintf(...) \ #define Log_TracePrintf(...) \
do \ do { \
{ \
} while (0) } while (0)
#endif #endif

View file

@ -5,23 +5,27 @@
/// ScopedGuard provides an object which runs a function (usually a lambda) when /// ScopedGuard provides an object which runs a function (usually a lambda) when
/// it goes out of scope. This can be useful for releasing resources or handles /// it goes out of scope. This can be useful for releasing resources or handles
/// which do not normally have C++ types to automatically release. /// which do not normally have C++ types to automatically release.
template<typename T> template <typename T>
class ScopedGuard final class ScopedGuard final {
{
public: public:
ALWAYS_INLINE ScopedGuard(T&& func) : m_func(std::forward<T>(func)) {} ALWAYS_INLINE ScopedGuard(T&& func) : m_func(std::forward<T>(func)) {}
ALWAYS_INLINE ScopedGuard(ScopedGuard&& other) : m_func(std::move(other.m_func)) { other.m_func = nullptr; } ALWAYS_INLINE ScopedGuard(ScopedGuard&& other) : m_func(std::move(other.m_func)) {
ALWAYS_INLINE ~ScopedGuard() { Invoke(); } other.m_func = nullptr;
}
ALWAYS_INLINE ~ScopedGuard() {
Invoke();
}
ScopedGuard(const ScopedGuard&) = delete; ScopedGuard(const ScopedGuard&) = delete;
void operator=(const ScopedGuard&) = delete; void operator=(const ScopedGuard&) = delete;
/// Prevents the function from being invoked when we go out of scope. /// Prevents the function from being invoked when we go out of scope.
ALWAYS_INLINE void Cancel() { m_func.reset(); } ALWAYS_INLINE void Cancel() {
m_func.reset();
}
/// Explicitly fires the function. /// Explicitly fires the function.
ALWAYS_INLINE void Invoke() ALWAYS_INLINE void Invoke() {
{
if (!m_func.has_value()) if (!m_func.has_value())
return; return;

View file

@ -1,70 +1,67 @@
#include "window_info.h"
#include "common/log.h" #include "common/log.h"
#include "window_info.h"
Log_SetChannel(WindowInfo); Log_SetChannel(WindowInfo);
#if defined(_WIN32) #if defined(_WIN32)
#include "common/windows_headers.h"
#include <dwmapi.h> #include <dwmapi.h>
#include "common/windows_headers.h"
static bool GetRefreshRateFromDWM(HWND hwnd, float* refresh_rate) static bool GetRefreshRateFromDWM(HWND hwnd, float* refresh_rate) {
{
static HMODULE dwm_module = nullptr; static HMODULE dwm_module = nullptr;
static HRESULT(STDAPICALLTYPE * is_composition_enabled)(BOOL * pfEnabled) = nullptr; static HRESULT(STDAPICALLTYPE * is_composition_enabled)(BOOL * pfEnabled) = nullptr;
static HRESULT(STDAPICALLTYPE * get_timing_info)(HWND hwnd, DWM_TIMING_INFO * pTimingInfo) = nullptr; static HRESULT(STDAPICALLTYPE * get_timing_info)(HWND hwnd, DWM_TIMING_INFO * pTimingInfo) =
nullptr;
static bool load_tried = false; static bool load_tried = false;
if (!load_tried) if (!load_tried) {
{
load_tried = true; load_tried = true;
dwm_module = LoadLibrary("dwmapi.dll"); dwm_module = LoadLibrary("dwmapi.dll");
if (dwm_module) if (dwm_module) {
{
std::atexit([]() { std::atexit([]() {
FreeLibrary(dwm_module); FreeLibrary(dwm_module);
dwm_module = nullptr; dwm_module = nullptr;
}); });
is_composition_enabled = is_composition_enabled = reinterpret_cast<decltype(is_composition_enabled)>(
reinterpret_cast<decltype(is_composition_enabled)>(GetProcAddress(dwm_module, "DwmIsCompositionEnabled")); GetProcAddress(dwm_module, "DwmIsCompositionEnabled"));
get_timing_info = get_timing_info = reinterpret_cast<decltype(get_timing_info)>(
reinterpret_cast<decltype(get_timing_info)>(GetProcAddress(dwm_module, "DwmGetCompositionTimingInfo")); GetProcAddress(dwm_module, "DwmGetCompositionTimingInfo"));
} }
} }
BOOL composition_enabled; BOOL composition_enabled;
if (!is_composition_enabled || FAILED(is_composition_enabled(&composition_enabled) || !get_timing_info)) if (!is_composition_enabled ||
FAILED(is_composition_enabled(&composition_enabled) || !get_timing_info))
return false; return false;
DWM_TIMING_INFO ti = {}; DWM_TIMING_INFO ti = {};
ti.cbSize = sizeof(ti); ti.cbSize = sizeof(ti);
HRESULT hr = get_timing_info(nullptr, &ti); HRESULT hr = get_timing_info(nullptr, &ti);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr)) {
{
if (ti.rateRefresh.uiNumerator == 0 || ti.rateRefresh.uiDenominator == 0) if (ti.rateRefresh.uiNumerator == 0 || ti.rateRefresh.uiDenominator == 0)
return false; return false;
*refresh_rate = static_cast<float>(ti.rateRefresh.uiNumerator) / static_cast<float>(ti.rateRefresh.uiDenominator); *refresh_rate = static_cast<float>(ti.rateRefresh.uiNumerator) /
static_cast<float>(ti.rateRefresh.uiDenominator);
return true; return true;
} }
return false; return false;
} }
static bool GetRefreshRateFromMonitor(HWND hwnd, float* refresh_rate) static bool GetRefreshRateFromMonitor(HWND hwnd, float* refresh_rate) {
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (!mon) if (!mon)
return false; return false;
MONITORINFOEXW mi = {}; MONITORINFOEXW mi = {};
mi.cbSize = sizeof(mi); mi.cbSize = sizeof(mi);
if (GetMonitorInfoW(mon, &mi)) if (GetMonitorInfoW(mon, &mi)) {
{
DEVMODEW dm = {}; DEVMODEW dm = {};
dm.dmSize = sizeof(dm); dm.dmSize = sizeof(dm);
// 0/1 are reserved for "defaults". // 0/1 are reserved for "defaults".
if (EnumDisplaySettingsW(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm) && dm.dmDisplayFrequency > 1) if (EnumDisplaySettingsW(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm) &&
{ dm.dmDisplayFrequency > 1) {
*refresh_rate = static_cast<float>(dm.dmDisplayFrequency); *refresh_rate = static_cast<float>(dm.dmDisplayFrequency);
return true; return true;
} }
@ -73,26 +70,25 @@ static bool GetRefreshRateFromMonitor(HWND hwnd, float* refresh_rate)
return false; return false;
} }
bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) {
{
if (wi.type != Type::Win32 || !wi.window_handle) if (wi.type != Type::Win32 || !wi.window_handle)
return false; return false;
// Try DWM first, then fall back to integer values. // Try DWM first, then fall back to integer values.
const HWND hwnd = static_cast<HWND>(wi.window_handle); const HWND hwnd = static_cast<HWND>(wi.window_handle);
return GetRefreshRateFromDWM(hwnd, refresh_rate) || GetRefreshRateFromMonitor(hwnd, refresh_rate); return GetRefreshRateFromDWM(hwnd, refresh_rate) ||
GetRefreshRateFromMonitor(hwnd, refresh_rate);
} }
#else #else
#ifdef USE_X11 #ifdef USE_X11
#include <X11/extensions/Xrandr.h>
#include "common/scoped_guard.h" #include "common/scoped_guard.h"
#include "gl/x11_window.h" #include "gl/x11_window.h"
#include <X11/extensions/Xrandr.h>
static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate) static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate) {
{
Display* display = static_cast<Display*>(wi.display_connection); Display* display = static_cast<Display*>(wi.display_connection);
Window window = static_cast<Window>(reinterpret_cast<uintptr_t>(wi.window_handle)); Window window = static_cast<Window>(reinterpret_cast<uintptr_t>(wi.window_handle));
if (!display || !window) if (!display || !window)
@ -101,8 +97,7 @@ static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate)
GL::X11InhibitErrors inhibiter; GL::X11InhibitErrors inhibiter;
XRRScreenResources* res = XRRGetScreenResources(display, window); XRRScreenResources* res = XRRGetScreenResources(display, window);
if (!res) if (!res) {
{
Log_ErrorPrint("XRRGetScreenResources() failed"); Log_ErrorPrint("XRRGetScreenResources() failed");
return false; return false;
} }
@ -111,30 +106,23 @@ static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate)
int num_monitors; int num_monitors;
XRRMonitorInfo* mi = XRRGetMonitors(display, window, True, &num_monitors); XRRMonitorInfo* mi = XRRGetMonitors(display, window, True, &num_monitors);
if (num_monitors < 0) if (num_monitors < 0) {
{
Log_ErrorPrint("XRRGetMonitors() failed"); Log_ErrorPrint("XRRGetMonitors() failed");
return false; return false;
} } else if (num_monitors > 1) {
else if (num_monitors > 1)
{
Log_WarningPrintf("XRRGetMonitors() returned %d monitors, using first", num_monitors); Log_WarningPrintf("XRRGetMonitors() returned %d monitors, using first", num_monitors);
} }
ScopedGuard mi_guard([mi]() { XRRFreeMonitors(mi); }); ScopedGuard mi_guard([mi]() { XRRFreeMonitors(mi); });
if (mi->noutput <= 0) if (mi->noutput <= 0) {
{
Log_ErrorPrint("Monitor has no outputs"); Log_ErrorPrint("Monitor has no outputs");
return false; return false;
} } else if (mi->noutput > 1) {
else if (mi->noutput > 1)
{
Log_WarningPrintf("Monitor has %d outputs, using first", mi->noutput); Log_WarningPrintf("Monitor has %d outputs, using first", mi->noutput);
} }
XRROutputInfo* oi = XRRGetOutputInfo(display, res, mi->outputs[0]); XRROutputInfo* oi = XRRGetOutputInfo(display, res, mi->outputs[0]);
if (!oi) if (!oi) {
{
Log_ErrorPrint("XRRGetOutputInfo() failed"); Log_ErrorPrint("XRRGetOutputInfo() failed");
return false; return false;
} }
@ -142,8 +130,7 @@ static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate)
ScopedGuard oi_guard([oi]() { XRRFreeOutputInfo(oi); }); ScopedGuard oi_guard([oi]() { XRRFreeOutputInfo(oi); });
XRRCrtcInfo* ci = XRRGetCrtcInfo(display, res, oi->crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(display, res, oi->crtc);
if (!ci) if (!ci) {
{
Log_ErrorPrint("XRRGetCrtcInfo() failed"); Log_ErrorPrint("XRRGetCrtcInfo() failed");
return false; return false;
} }
@ -151,35 +138,32 @@ static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate)
ScopedGuard ci_guard([ci]() { XRRFreeCrtcInfo(ci); }); ScopedGuard ci_guard([ci]() { XRRFreeCrtcInfo(ci); });
XRRModeInfo* mode = nullptr; XRRModeInfo* mode = nullptr;
for (int i = 0; i < res->nmode; i++) for (int i = 0; i < res->nmode; i++) {
{ if (res->modes[i].id == ci->mode) {
if (res->modes[i].id == ci->mode)
{
mode = &res->modes[i]; mode = &res->modes[i];
break; break;
} }
} }
if (!mode) if (!mode) {
{ Log_ErrorPrintf("Failed to look up mode %d (of %d)", static_cast<int>(ci->mode),
Log_ErrorPrintf("Failed to look up mode %d (of %d)", static_cast<int>(ci->mode), res->nmode); res->nmode);
return false; return false;
} }
if (mode->dotClock == 0 || mode->hTotal == 0 || mode->vTotal == 0) if (mode->dotClock == 0 || mode->hTotal == 0 || mode->vTotal == 0) {
{ Log_ErrorPrintf("Modeline is invalid: %ld/%d/%d", mode->dotClock, mode->hTotal,
Log_ErrorPrintf("Modeline is invalid: %ld/%d/%d", mode->dotClock, mode->hTotal, mode->vTotal); mode->vTotal);
return false; return false;
} }
*refresh_rate = *refresh_rate = static_cast<double>(mode->dotClock) /
static_cast<double>(mode->dotClock) / (static_cast<double>(mode->hTotal) * static_cast<double>(mode->vTotal)); (static_cast<double>(mode->hTotal) * static_cast<double>(mode->vTotal));
return true; return true;
} }
#endif // USE_X11 #endif // USE_X11
bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) {
{
#if defined(USE_X11) #if defined(USE_X11)
if (wi.type == WindowInfo::Type::X11) if (wi.type == WindowInfo::Type::X11)
return GetRefreshRateFromXRandR(wi, refresh_rate); return GetRefreshRateFromXRandR(wi, refresh_rate);

View file

@ -2,10 +2,8 @@
#include "../types.h" #include "../types.h"
// Contains the information required to create a graphics context in a window. // Contains the information required to create a graphics context in a window.
struct WindowInfo struct WindowInfo {
{ enum class Type {
enum class Type
{
Surfaceless, Surfaceless,
Win32, Win32,
X11, X11,
@ -15,15 +13,7 @@ struct WindowInfo
Display, Display,
}; };
enum class SurfaceFormat enum class SurfaceFormat { None, Auto, RGB8, RGBA8, RGB565, Count };
{
None,
Auto,
RGB8,
RGBA8,
RGB565,
Count
};
Type type = Type::Surfaceless; Type type = Type::Surfaceless;
void* display_connection = nullptr; void* display_connection = nullptr;

View file

@ -19,11 +19,10 @@
#ifndef TYPES_H #ifndef TYPES_H
#define TYPES_H #define TYPES_H
#include <stdint.h>
#include <array> #include <array>
#include <stdint.h>
namespace citra namespace citra {
{
typedef uint8_t u8; typedef uint8_t u8;
typedef uint16_t u16; typedef uint16_t u16;
typedef uint32_t u32; typedef uint32_t u32;
@ -33,7 +32,7 @@ typedef int16_t s16;
typedef int32_t s32; typedef int32_t s32;
typedef int64_t s64; typedef int64_t s64;
template<class T, std::size_t A, std::size_t B> template <class T, std::size_t A, std::size_t B>
using array2d = std::array<std::array<T, B>, A>; using array2d = std::array<std::array<T, B>, A>;
} } // namespace citra
#endif // TYPES_H #endif // TYPES_H