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 AssertMsg(cond, msg) assert(cond && msg)
#define AssertMsg(cond, msg) assert(cond&& msg)
#define Assert(cond) assert(cond)
#define Panic(msg) assert(false && msg)

View file

@ -1,9 +1,9 @@
#include "context.h"
#include "../log.h"
#include "loader.h"
#include <cstdlib>
#include <cstring>
#include <stdlib.h>
#include "../log.h"
#include "context.h"
#include "loader.h"
Log_SetChannel(GL::Context);
#if defined(_WIN32)
@ -20,8 +20,7 @@ Log_SetChannel(GL::Context);
namespace GL {
static bool ShouldPreferESContext()
{
static bool ShouldPreferESContext() {
#ifndef _MSC_VER
const char* value = std::getenv("PREFER_GLES_CONTEXT");
return (value && strcmp(value, "1") == 0);
@ -37,26 +36,22 @@ Context::Context(const WindowInfo& wi) : m_wi(wi) {}
Context::~Context() = default;
std::vector<Context::FullscreenModeInfo> Context::EnumerateFullscreenModes()
{
std::vector<Context::FullscreenModeInfo> Context::EnumerateFullscreenModes() {
return {};
}
std::unique_ptr<GL::Context> Context::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try)
{
if (ShouldPreferESContext())
{
size_t num_versions_to_try) {
if (ShouldPreferESContext()) {
// 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;
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)
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)
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__)
context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try);
#else
if (wi.type == WindowInfo::Type::X11)
{
if (wi.type == WindowInfo::Type::X11) {
const char* use_egl_x11 = std::getenv("USE_EGL_X11");
if (use_egl_x11 && std::strcmp(use_egl_x11, "1") == 0)
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;
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");
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_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
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_RENDERER: %s", gl_renderer);
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;
}
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},
{Profile::Core, 4, 5},
{Profile::Core, 4, 4},
@ -127,8 +121,7 @@ const std::array<Context::Version, 11>& Context::GetAllDesktopVersionsList()
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},
{Profile::Core, 4, 5},
{Profile::Core, 4, 4},
@ -144,15 +137,13 @@ const std::array<Context::Version, 12>& Context::GetAllDesktopVersionsListWithFa
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 = {
{{Profile::ES, 3, 2}, {Profile::ES, 3, 1}, {Profile::ES, 3, 0}, {Profile::ES, 2, 0}}};
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},
{Profile::Core, 4, 5},
{Profile::Core, 4, 4},

View file

@ -1,44 +1,46 @@
#pragma once
#include "../duckstation_compat.h"
#include "../window_info.h"
#include <array>
#include <memory>
#include <vector>
#include "../duckstation_compat.h"
#include "../window_info.h"
namespace GL {
using namespace citra;
class Context
{
class Context {
public:
Context(const WindowInfo& wi);
virtual ~Context();
enum class Profile
{
NoProfile,
Core,
ES
};
enum class Profile { NoProfile, Core, ES };
struct Version
{
struct Version {
Profile profile;
int major_version;
int minor_version;
};
struct FullscreenModeInfo
{
struct FullscreenModeInfo {
u32 width;
u32 height;
float refresh_rate;
};
ALWAYS_INLINE const WindowInfo& GetWindowInfo() const { return m_wi; }
ALWAYS_INLINE bool IsGLES() const { 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; }
ALWAYS_INLINE const WindowInfo& GetWindowInfo() const {
return m_wi;
}
ALWAYS_INLINE bool IsGLES() const {
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 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,
size_t num_versions_to_try);
template<size_t N>
static std::unique_ptr<Context> Create(const WindowInfo& wi, const std::array<Version, N>& versions_to_try)
{
template <size_t N>
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());
}
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, 12>& GetAllDesktopVersionsListWithFallback();

View file

@ -14,8 +14,7 @@ struct NSView;
namespace GL {
using namespace melonDS;
class ContextAGL final : public Context
{
class ContextAGL final : public Context {
public:
ContextAGL(const WindowInfo& wi);
~ContextAGL() override;
@ -33,7 +32,9 @@ public:
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
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 CreateContext(NSOpenGLContext* share_context, int profile, bool make_current);

View file

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

View file

@ -1,11 +1,10 @@
#pragma once
#include "context.h"
#include "../../../../../externals/glad/src/glad_egl.h"
#include "context.h"
namespace GL {
class ContextEGL : public Context
{
class ContextEGL : public Context {
public:
ContextEGL(const WindowInfo& wi);
~ContextEGL() override;
@ -29,7 +28,8 @@ protected:
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
bool CreateDisplay();
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 CreatePBufferSurface();
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 "../log.h"
#include "context_egl_wayland.h"
Log_SetChannel(ContextEGLWayland);
namespace GL {
static const char* WAYLAND_EGL_MODNAME = "libwayland-egl.so.1";
ContextEGLWayland::ContextEGLWayland(const WindowInfo& wi) : ContextEGL(wi) {}
ContextEGLWayland::~ContextEGLWayland()
{
ContextEGLWayland::~ContextEGLWayland() {
if (m_wl_window)
m_wl_egl_window_destroy(m_wl_window);
if (m_wl_module)
dlclose(m_wl_module);
}
std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try)
{
std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi,
const Version* versions_to_try,
size_t num_versions_to_try) {
std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
if (!context->LoadModule() || !context->Initialize(versions_to_try, num_versions_to_try))
return nullptr;
@ -25,8 +24,7 @@ std::unique_ptr<Context> ContextEGLWayland::Create(const WindowInfo& wi, const V
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);
context->m_display = m_display;
@ -36,47 +34,41 @@ std::unique_ptr<Context> ContextEGLWayland::CreateSharedContext(const WindowInfo
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)
m_wl_egl_window_resize(m_wl_window, new_surface_width, new_surface_height, 0, 0);
ContextEGL::ResizeSurface(new_surface_width, new_surface_height);
}
EGLNativeWindowType ContextEGLWayland::GetNativeWindow(EGLConfig config)
{
if (m_wl_window)
{
EGLNativeWindowType ContextEGLWayland::GetNativeWindow(EGLConfig config) {
if (m_wl_window) {
m_wl_egl_window_destroy(m_wl_window);
m_wl_window = nullptr;
}
m_wl_window =
m_wl_egl_window_create(static_cast<wl_surface*>(m_wi.window_handle), m_wi.surface_width, m_wi.surface_height);
m_wl_window = m_wl_egl_window_create(static_cast<wl_surface*>(m_wi.window_handle),
m_wi.surface_width, m_wi.surface_height);
if (!m_wl_window)
return {};
return reinterpret_cast<EGLNativeWindowType>(m_wl_window);
}
bool ContextEGLWayland::LoadModule()
{
bool ContextEGLWayland::LoadModule() {
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);
return false;
}
m_wl_egl_window_create =
reinterpret_cast<decltype(m_wl_egl_window_create)>(dlsym(m_wl_module, "wl_egl_window_create"));
m_wl_egl_window_destroy =
reinterpret_cast<decltype(m_wl_egl_window_destroy)>(dlsym(m_wl_module, "wl_egl_window_destroy"));
m_wl_egl_window_resize =
reinterpret_cast<decltype(m_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)
{
m_wl_egl_window_create = reinterpret_cast<decltype(m_wl_egl_window_create)>(
dlsym(m_wl_module, "wl_egl_window_create"));
m_wl_egl_window_destroy = reinterpret_cast<decltype(m_wl_egl_window_destroy)>(
dlsym(m_wl_module, "wl_egl_window_destroy"));
m_wl_egl_window_resize = reinterpret_cast<decltype(m_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) {
Log_ErrorPrintf("Failed to load one or more functions from %s.", WAYLAND_EGL_MODNAME);
return false;
}

View file

@ -1,11 +1,10 @@
#pragma once
#include "context_egl.h"
#include <wayland-egl.h>
#include "context_egl.h"
namespace GL {
class ContextEGLWayland final : public ContextEGL
{
class ContextEGLWayland final : public ContextEGL {
public:
ContextEGLWayland(const WindowInfo& wi);
~ContextEGLWayland() override;
@ -27,7 +26,8 @@ private:
void* m_wl_module = nullptr;
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_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

View file

@ -1,5 +1,5 @@
#include "context_egl_x11.h"
#include "../log.h"
#include "context_egl_x11.h"
Log_SetChannel(GL::ContextEGLX11);
namespace GL {
@ -7,8 +7,7 @@ ContextEGLX11::ContextEGLX11(const WindowInfo& wi) : ContextEGL(wi) {}
ContextEGLX11::~ContextEGLX11() = default;
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);
if (!context->Initialize(versions_to_try, num_versions_to_try))
return nullptr;
@ -16,8 +15,7 @@ std::unique_ptr<Context> ContextEGLX11::Create(const WindowInfo& wi, const Versi
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);
context->m_display = m_display;
@ -27,19 +25,16 @@ std::unique_ptr<Context> ContextEGLX11::CreateSharedContext(const WindowInfo& wi
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();
ContextEGL::ResizeSurface(new_surface_width, new_surface_height);
}
EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config)
{
EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config) {
X11InhibitErrors ei;
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");
return false;
}
@ -48,16 +43,17 @@ EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config)
vi_query.visualid = native_visual_id;
int num_vis;
XVisualInfo* vi = XGetVisualInfo(static_cast<Display*>(m_wi.display_connection), VisualIDMask, &vi_query, &num_vis);
if (num_vis <= 0 || !vi)
{
XVisualInfo* vi = XGetVisualInfo(static_cast<Display*>(m_wi.display_connection), VisualIDMask,
&vi_query, &num_vis);
if (num_vis <= 0 || !vi) {
Log_ErrorPrintf("Failed to query visual from X11");
return false;
}
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");
XFree(vi);
return false;

View file

@ -4,8 +4,7 @@
namespace GL {
class ContextEGLX11 final : public ContextEGL
{
class ContextEGLX11 final : public ContextEGL {
public:
ContextEGLX11(const WindowInfo& wi);
~ContextEGLX11() override;
@ -20,7 +19,9 @@ protected:
EGLNativeWindowType GetNativeWindow(EGLConfig config) override;
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;
};

View file

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

View file

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

View file

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

View file

@ -1,15 +1,14 @@
#pragma once
#include "../windows_headers.h"
#include "context.h"
#include "../../../../../externals/glad/src/glad_wgl.h"
#include "loader.h"
#include <optional>
#include "../../../../../externals/glad/src/glad_wgl.h"
#include "context.h"
#include "loader.h"
namespace GL {
class ContextWGL final : public Context
{
class ContextWGL final : public Context {
public:
ContextWGL(const WindowInfo& wi);
~ContextWGL() override;
@ -27,7 +26,9 @@ public:
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
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);

View file

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

View file

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

View file

@ -5,41 +5,73 @@
#define Log_SetChannel(ChannelName)
#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_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_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_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_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_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_ProfilePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0)
#define Log_ProfilePrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#ifdef _DEBUG
#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_TracePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0)
#define Log_TracePrintf(...) \
do { \
printf(__VA_ARGS__); \
putchar('\n'); \
} while (0)
#else
#define Log_DebugPrint(msg) \
do \
{ \
do { \
} while (0)
#define Log_DebugPrintf(...) \
do \
{ \
do { \
} while (0)
#define Log_TracePrint(msg) \
do \
{ \
do { \
} while (0)
#define Log_TracePrintf(...) \
do \
{ \
do { \
} while (0)
#endif

View file

@ -5,23 +5,27 @@
/// 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
/// which do not normally have C++ types to automatically release.
template<typename T>
class ScopedGuard final
{
template <typename T>
class ScopedGuard final {
public:
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() { Invoke(); }
ALWAYS_INLINE ScopedGuard(ScopedGuard&& other) : m_func(std::move(other.m_func)) {
other.m_func = nullptr;
}
ALWAYS_INLINE ~ScopedGuard() {
Invoke();
}
ScopedGuard(const ScopedGuard&) = delete;
void operator=(const ScopedGuard&) = delete;
/// 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.
ALWAYS_INLINE void Invoke()
{
ALWAYS_INLINE void Invoke() {
if (!m_func.has_value())
return;

View file

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

View file

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

View file

@ -19,11 +19,10 @@
#ifndef TYPES_H
#define TYPES_H
#include <stdint.h>
#include <array>
#include <stdint.h>
namespace citra
{
namespace citra {
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
@ -33,7 +32,7 @@ typedef int16_t s16;
typedef int32_t s32;
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>;
}
} // namespace citra
#endif // TYPES_H