This commit is contained in:
wheremyfoodat
2023-09-30 01:35:26 +03:00
parent 42cbcc1380
commit 5d9ded47da
35 changed files with 37343 additions and 21800 deletions
+18 -2
View File
@@ -225,6 +225,22 @@ set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp
third_party/cityhash/cityhash.cpp
third_party/xxhash/xxhash.c
)
if(ENABLE_QT_GUI)
include_directories(third_party/duckstation)
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/window_info.cpp third_party/duckstation/gl/context.cpp)
if(APPLE)
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_agl.mm)
elseif(WIN32)
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_wgl.cpp)
else()
set(THIRD_PARTY_SOURCE_FILES ${THIRD_PARTY_SOURCE_FILES} third_party/duckstation/gl/context_egl.cpp third_party/duckstation/gl/context_egl_wayland.cpp
third_party/duckstation/gl/context_egl_x11.cpp third_party/duckstation/gl/context_glx.cpp third_party/duckstation/gl/x11_window.cpp)
endif()
endif()
source_group("Source Files\\Core" FILES ${SOURCE_FILES})
source_group("Source Files\\Core\\Crypto" FILES ${CRYPTO_SOURCE_FILES})
source_group("Source Files\\Core\\Filesystem" FILES ${FS_SOURCE_FILES})
@@ -304,9 +320,9 @@ if(ENABLE_VULKAN)
if(GPU_DEBUG_INFO)
# generate nonsemantic shader debug information with source
set( RENDERER_VK_HOST_SHADERS_FLAGS ${RENDERER_VK_HOST_SHADERS_FLAGS} -gVS)
set(RENDERER_VK_HOST_SHADERS_FLAGS ${RENDERER_VK_HOST_SHADERS_FLAGS} -gVS)
else()
set( RENDERER_VK_HOST_SHADERS_FLAGS ${RENDERER_VK_HOST_SHADERS_FLAGS} -g0)
set(RENDERER_VK_HOST_SHADERS_FLAGS ${RENDERER_VK_HOST_SHADERS_FLAGS} -g0)
endif()
# Compile each vulkan shader into an .spv file
+1 -1
View File
@@ -58,7 +58,7 @@ Emulator::Emulator()
Helpers::panic("OpenGL context creation failed: %s", SDL_GetError());
}
if (!gladLoadGL(reinterpret_cast<GLADloadfunc>(SDL_GL_GetProcAddress))) {
if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(SDL_GL_GetProcAddress))) {
Helpers::panic("OpenGL init failed: %s", SDL_GetError());
}
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef DUCKSTATION_COMPAT_H
#define DUCKSTATION_COMPAT_H
#include <assert.h>
#include "compiler_builtins.hpp"
#include "helpers.hpp"
#define AssertMsg(cond, msg) assert(cond&& msg)
#define Assert(cond) assert(cond)
#define Panic(msg) assert(false && msg)
#define UnreachableCode() __builtin_unreachable()
#endif
+46
View File
@@ -0,0 +1,46 @@
#ifndef LOG_H
#define LOG_H
#include <stdio.h>
#define Log_SetChannel(ChannelName)
#define Log_ErrorPrint(msg) puts(msg "\n");
#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_PerfPrint(msg) puts(msg)
#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_VerbosePrint(msg) puts(msg)
#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_ProfilePrint(msg) puts(msg)
#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_TracePrint(msg) puts(msg)
#define Log_TracePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0)
#else
#define Log_DebugPrint(msg) \
do \
{ \
} while (0)
#define Log_DebugPrintf(...) \
do \
{ \
} while (0)
#define Log_TracePrint(msg) \
do \
{ \
} while (0)
#define Log_TracePrintf(...) \
do \
{ \
} while (0)
#endif
#endif
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <optional>
#include <utility>
/// 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
{
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(); }
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(); }
/// Explicitly fires the function.
ALWAYS_INLINE void Invoke()
{
if (!m_func.has_value())
return;
m_func.value()();
m_func.reset();
}
private:
std::optional<T> m_func;
};
+179
View File
@@ -0,0 +1,179 @@
#include "context.h"
#include "duckstation_log.h"
#include "loader.h"
#include <cstdlib>
#include <cstring>
#ifdef __APPLE__
#include <stdlib.h>
#else
#include <malloc.h>
#endif
Log_SetChannel(GL::Context);
#if defined(_WIN32)
#include "context_wgl.h"
#elif defined(__APPLE__)
#include "context_agl.h"
#else
#ifdef WAYLAND_ENABLED
#include "context_egl_wayland.h"
#endif
#include "context_egl_x11.h"
#include "context_glx.h"
#endif
namespace GL {
static bool ShouldPreferESContext()
{
#ifndef _MSC_VER
const char* value = std::getenv("PREFER_GLES_CONTEXT");
return (value && strcmp(value, "1") == 0);
#else
char buffer[2] = {};
size_t buffer_size = sizeof(buffer);
getenv_s(&buffer_size, buffer, "PREFER_GLES_CONTEXT");
return (std::strcmp(buffer, "1") == 0);
#endif
}
Context::Context(const WindowInfo& wi) : m_wi(wi) {}
Context::~Context() = default;
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())
{
// move ES versions to the front
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++)
{
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++)
{
if (versions_to_try[i].profile != Profile::ES)
new_versions_to_try[count++] = versions_to_try[i];
}
versions_to_try = new_versions_to_try;
}
std::unique_ptr<Context> context;
#if defined(_WIN32)
context = ContextWGL::Create(wi, versions_to_try, num_versions_to_try);
#elif defined(__APPLE__)
context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try);
#else
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);
else
context = ContextGLX::Create(wi, versions_to_try, num_versions_to_try);
}
#ifdef WAYLAND_ENABLED
if (wi.type == WindowInfo::Type::Wayland)
context = ContextEGLWayland::Create(wi, versions_to_try, num_versions_to_try);
#endif
#endif
if (!context)
return nullptr;
Log_InfoPrintf("Created a %s context", context->IsGLES() ? "OpenGL ES" : "OpenGL");
// TODO: Not thread-safe.
static Context* context_being_created;
context_being_created = context.get();
if (!gladLoadGLLoader([](const char* name) { return context_being_created->GetProcAddress(name); }))
{
Log_ErrorPrintf("Failed to load GL functions for GLAD");
return nullptr;
}
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));
Log_InfoPrintf("GL_VENDOR: %s", gl_vendor);
Log_InfoPrintf("GL_RENDERER: %s", gl_renderer);
Log_InfoPrintf("GL_VERSION: %s", gl_version);
Log_InfoPrintf("GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version);
return context;
}
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},
{Profile::Core, 4, 3},
{Profile::Core, 4, 2},
{Profile::Core, 4, 1},
{Profile::Core, 4, 0},
{Profile::Core, 3, 3},
{Profile::Core, 3, 2},
{Profile::Core, 3, 1},
{Profile::Core, 3, 0}}};
return vlist;
}
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},
{Profile::Core, 4, 3},
{Profile::Core, 4, 2},
{Profile::Core, 4, 1},
{Profile::Core, 4, 0},
{Profile::Core, 3, 3},
{Profile::Core, 3, 2},
{Profile::Core, 3, 1},
{Profile::Core, 3, 0},
{Profile::NoProfile, 0, 0}}};
return vlist;
}
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()
{
static constexpr std::array<Version, 16> vlist = {{{Profile::Core, 4, 6},
{Profile::Core, 4, 5},
{Profile::Core, 4, 4},
{Profile::Core, 4, 3},
{Profile::Core, 4, 2},
{Profile::Core, 4, 1},
{Profile::Core, 4, 0},
{Profile::Core, 3, 3},
{Profile::Core, 3, 2},
{Profile::Core, 3, 1},
{Profile::Core, 3, 0},
{Profile::ES, 3, 2},
{Profile::ES, 3, 1},
{Profile::ES, 3, 0},
{Profile::ES, 2, 0},
{Profile::NoProfile, 0, 0}}};
return vlist;
}
} // namespace GL
+76
View File
@@ -0,0 +1,76 @@
#pragma once
#include "duckstation_compat.h"
#include "window_info.h"
#include <array>
#include <memory>
#include <vector>
namespace GL {
class Context
{
public:
Context(const WindowInfo& wi);
virtual ~Context();
enum class Profile
{
NoProfile,
Core,
ES
};
struct Version
{
Profile profile;
int major_version;
int minor_version;
};
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; }
virtual void* GetProcAddress(const char* name) = 0;
virtual bool ChangeSurface(const WindowInfo& new_wi) = 0;
virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) = 0;
virtual bool SwapBuffers() = 0;
virtual bool MakeCurrent() = 0;
virtual bool DoneCurrent() = 0;
virtual bool SetSwapInterval(s32 interval) = 0;
virtual std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) = 0;
virtual std::vector<FullscreenModeInfo> EnumerateFullscreenModes();
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)
{
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 const std::array<Version, 11>& GetAllDesktopVersionsList();
static const std::array<Version, 12>& GetAllDesktopVersionsListWithFallback();
static const std::array<Version, 4>& GetAllESVersionsList();
static const std::array<Version, 16>& GetAllVersionsList();
protected:
#ifdef _WIN32
#endif
WindowInfo m_wi;
Version m_version = {};
};
} // namespace GL
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#include "context.h"
#include "loader.h"
#if defined(__APPLE__) && defined(__OBJC__)
#import <AppKit/AppKit.h>
#else
struct NSOpenGLContext;
struct NSOpenGLPixelFormat;
struct NSView;
#define __bridge
#endif
namespace GL {
class ContextAGL final : public Context
{
public:
ContextAGL(const WindowInfo& wi);
~ContextAGL() override;
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try);
void* GetProcAddress(const char* name) override;
bool ChangeSurface(const WindowInfo& new_wi) override;
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
bool SwapBuffers() override;
bool MakeCurrent() override;
bool DoneCurrent() override;
bool SetSwapInterval(s32 interval) override;
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); }
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
bool CreateContext(NSOpenGLContext* share_context, int profile, bool make_current);
void BindContextToView();
// returns true if dimensions have changed
bool UpdateDimensions();
NSOpenGLContext* m_context = nullptr;
NSOpenGLPixelFormat* m_pixel_format = nullptr;
void* m_opengl_module_handle = nullptr;
};
} // namespace GL
+214
View File
@@ -0,0 +1,214 @@
#include "context_agl.h"
#include "duckstation_compat.h"
#include "duckstation_log.h"
#include "loader.h"
#include <dlfcn.h>
Log_SetChannel(GL::ContextAGL);
namespace GL {
ContextAGL::ContextAGL(const WindowInfo& wi) : Context(wi)
{
m_opengl_module_handle = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_NOW);
if (!m_opengl_module_handle)
Log_ErrorPrint("Could not open OpenGL.framework, function lookups will probably fail");
}
ContextAGL::~ContextAGL()
{
if ([NSOpenGLContext currentContext] == m_context)
[NSOpenGLContext clearCurrentContext];
if (m_context)
[m_context release];
if (m_pixel_format)
[m_pixel_format release];
if (m_opengl_module_handle)
dlclose(m_opengl_module_handle);
}
std::unique_ptr<Context> ContextAGL::Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try)
{
std::unique_ptr<ContextAGL> context = std::make_unique<ContextAGL>(wi);
if (!context->Initialize(versions_to_try, num_versions_to_try))
return nullptr;
return context;
}
bool ContextAGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try)
{
for (size_t i = 0; i < num_versions_to_try; i++)
{
const Version& cv = versions_to_try[i];
if (cv.profile == Profile::NoProfile && CreateContext(nullptr, NSOpenGLProfileVersionLegacy, true))
{
// we already have the dummy context, so just use that
m_version = cv;
return true;
}
else if (cv.profile == Profile::Core)
{
if (cv.major_version > 4 && cv.minor_version > 1)
continue;
const NSOpenGLPixelFormatAttribute profile = (cv.major_version > 3 || cv.minor_version > 2) ? NSOpenGLProfileVersion4_1Core : NSOpenGLProfileVersion3_2Core;
if (CreateContext(nullptr, static_cast<int>(profile), true))
{
m_version = cv;
return true;
}
}
}
return false;
}
void* ContextAGL::GetProcAddress(const char* name)
{
void* addr = m_opengl_module_handle ? dlsym(m_opengl_module_handle, name) : nullptr;
if (addr)
return addr;
return dlsym(RTLD_NEXT, name);
}
bool ContextAGL::ChangeSurface(const WindowInfo& new_wi)
{
m_wi = new_wi;
BindContextToView();
return true;
}
void ContextAGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/)
{
UpdateDimensions();
}
bool ContextAGL::UpdateDimensions()
{
const NSSize window_size = [GetView() frame].size;
const CGFloat window_scale = [[GetView() window] backingScaleFactor];
const u32 new_width = static_cast<u32>(static_cast<CGFloat>(window_size.width) * window_scale);
const u32 new_height = static_cast<u32>(static_cast<CGFloat>(window_size.height) * window_scale);
if (m_wi.surface_width == new_width && m_wi.surface_height == new_height)
return false;
m_wi.surface_width = new_width;
m_wi.surface_height = new_height;
dispatch_block_t block = ^{
[m_context update];
};
if ([NSThread isMainThread])
block();
else
dispatch_sync(dispatch_get_main_queue(), block);
return true;
}
bool ContextAGL::SwapBuffers()
{
[m_context flushBuffer];
return true;
}
bool ContextAGL::MakeCurrent()
{
[m_context makeCurrentContext];
return true;
}
bool ContextAGL::DoneCurrent()
{
[NSOpenGLContext clearCurrentContext];
return true;
}
bool ContextAGL::SetSwapInterval(s32 interval)
{
GLint gl_interval = static_cast<GLint>(interval);
[m_context setValues:&gl_interval forParameter:NSOpenGLCPSwapInterval];
return true;
}
std::unique_ptr<Context> ContextAGL::CreateSharedContext(const WindowInfo& wi)
{
std::unique_ptr<ContextAGL> context = std::make_unique<ContextAGL>(wi);
context->m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:m_context];
if (context->m_context == nil)
return nullptr;
context->m_version = m_version;
context->m_pixel_format = m_pixel_format;
[context->m_pixel_format retain];
if (wi.type == WindowInfo::Type::MacOS)
context->BindContextToView();
return context;
}
bool ContextAGL::CreateContext(NSOpenGLContext* share_context, int profile, bool make_current)
{
if (m_context)
{
[m_context release];
m_context = nullptr;
}
if (m_pixel_format)
[m_pixel_format release];
const std::array<NSOpenGLPixelFormatAttribute, 5> attribs = {{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAOpenGLProfile,
static_cast<NSOpenGLPixelFormatAttribute>(profile),
NSOpenGLPFAAccelerated,
0}};
m_pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs.data()];
if (m_pixel_format == nil)
{
Log_ErrorPrintf("Failed to initialize pixel format");
return false;
}
m_context = [[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:nil];
if (m_context == nil)
return false;
if (m_wi.type == WindowInfo::Type::MacOS)
BindContextToView();
if (make_current)
[m_context makeCurrentContext];
return true;
}
void ContextAGL::BindContextToView()
{
NSView* const view = GetView();
NSWindow* const window = [view window];
[view setWantsBestResolutionOpenGLSurface:YES];
UpdateDimensions();
dispatch_block_t block = ^{
[window makeFirstResponder:view];
[m_context setView:view];
[window makeKeyAndOrderFront:nil];
};
if ([NSThread isMainThread])
block();
else
dispatch_sync(dispatch_get_main_queue(), block);
}
} // namespace GL
+432
View File
@@ -0,0 +1,432 @@
#include "context_egl.h"
#include "duckstation_log.h"
#include "duckstation_compat.h"
#include <optional>
#include <vector>
#include <cstring>
Log_SetChannel(GL::ContextEGL);
namespace GL {
ContextEGL::ContextEGL(const WindowInfo& wi) : Context(wi) {}
ContextEGL::~ContextEGL()
{
DestroySurface();
DestroyContext();
}
std::unique_ptr<Context> ContextEGL::Create(const WindowInfo& wi, const Version* 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;
return context;
}
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;
}
if (!SetDisplay())
return false;
int 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)
{
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");
for (size_t i = 0; i < num_versions_to_try; i++)
{
if (CreateContextAndSurface(versions_to_try[i], nullptr, true))
return true;
}
return false;
}
bool ContextEGL::SetDisplay()
{
m_display = eglGetDisplay(static_cast<EGLNativeDisplayType>(m_wi.display_connection));
if (!m_display)
{
Log_ErrorPrintf("eglGetDisplay() failed: %d", eglGetError());
return false;
}
return true;
}
void* ContextEGL::GetProcAddress(const char* name)
{
return reinterpret_cast<void*>(eglGetProcAddress(name));
}
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)
{
eglDestroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE;
}
m_wi = new_wi;
if (!CreateSurface())
return false;
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;
}
return true;
}
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))
{
m_wi.surface_width = static_cast<u32>(surface_width);
m_wi.surface_height = static_cast<u32>(surface_height);
return;
}
else
{
Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError());
}
}
m_wi.surface_width = new_surface_width;
m_wi.surface_height = new_surface_height;
}
bool ContextEGL::SwapBuffers()
{
return eglSwapBuffers(m_display, m_surface);
}
bool ContextEGL::MakeCurrent()
{
if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context))
{
Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError());
return false;
}
return true;
}
bool ContextEGL::DoneCurrent()
{
return eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
bool ContextEGL::SetSwapInterval(s32 interval)
{
return eglSwapInterval(m_display, interval);
}
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;
if (!context->CreateContextAndSurface(m_version, m_context, false))
return nullptr;
return context;
}
EGLNativeWindowType ContextEGL::GetNativeWindow(EGLConfig config)
{
return {};
}
bool ContextEGL::CreateSurface()
{
if (m_wi.type == WindowInfo::Type::Surfaceless)
{
if (m_supports_surfaceless)
return true;
else
return CreatePBufferSurface();
}
EGLNativeWindowType native_window = GetNativeWindow(m_config);
m_surface = eglCreateWindowSurface(m_display, m_config, native_window, nullptr);
if (!m_surface)
{
Log_ErrorPrintf("eglCreateWindowSurface() failed: %d", eglGetError());
return false;
}
// 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))
{
m_wi.surface_width = static_cast<u32>(surface_width);
m_wi.surface_height = static_cast<u32>(surface_height);
}
else
{
Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError());
}
return true;
}
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);
// TODO: Format
EGLint attrib_list[] = {
EGL_WIDTH, static_cast<EGLint>(width), EGL_HEIGHT, static_cast<EGLint>(height), EGL_NONE,
};
m_surface = eglCreatePbufferSurface(m_display, m_config, attrib_list);
if (!m_surface)
{
Log_ErrorPrintf("eglCreatePbufferSurface() failed: %d", eglGetError());
return false;
}
Log_DevPrintf("Created %ux%u pbuffer surface", width, height);
return true;
}
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))
{
return false;
}
switch (format)
{
case WindowInfo::SurfaceFormat::Auto:
return true;
case WindowInfo::SurfaceFormat::RGB8:
return (red_size == 8 && green_size == 8 && blue_size == 8);
case WindowInfo::SurfaceFormat::RGBA8:
return (red_size == 8 && green_size == 8 && blue_size == 8 && alpha_size == 8);
case WindowInfo::SurfaceFormat::RGB565:
return (red_size == 5 && green_size == 6 && blue_size == 5);
default:
return false;
}
}
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)
{
eglDestroyContext(m_display, m_context);
m_context = EGL_NO_CONTEXT;
}
}
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)
{
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"));
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,
EGL_SURFACE_TYPE,
(m_wi.type != WindowInfo::Type::Surfaceless) ? EGL_WINDOW_BIT : 0,
};
int nsurface_attribs = 4;
switch (m_wi.surface_format)
{
case WindowInfo::SurfaceFormat::RGB8:
surface_attribs[nsurface_attribs++] = EGL_RED_SIZE;
surface_attribs[nsurface_attribs++] = 8;
surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE;
surface_attribs[nsurface_attribs++] = 8;
surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE;
surface_attribs[nsurface_attribs++] = 8;
break;
case WindowInfo::SurfaceFormat::RGBA8:
surface_attribs[nsurface_attribs++] = EGL_RED_SIZE;
surface_attribs[nsurface_attribs++] = 8;
surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE;
surface_attribs[nsurface_attribs++] = 8;
surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE;
surface_attribs[nsurface_attribs++] = 8;
surface_attribs[nsurface_attribs++] = EGL_ALPHA_SIZE;
surface_attribs[nsurface_attribs++] = 8;
break;
case WindowInfo::SurfaceFormat::RGB565:
surface_attribs[nsurface_attribs++] = EGL_RED_SIZE;
surface_attribs[nsurface_attribs++] = 5;
surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE;
surface_attribs[nsurface_attribs++] = 6;
surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE;
surface_attribs[nsurface_attribs++] = 5;
break;
case WindowInfo::SurfaceFormat::Auto:
break;
default:
UnreachableCode();
break;
}
surface_attribs[nsurface_attribs++] = EGL_NONE;
surface_attribs[nsurface_attribs++] = 0;
EGLint num_configs;
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))
{
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))
{
config = check_config;
break;
}
}
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)
{
attribs[nattribs++] = EGL_CONTEXT_MAJOR_VERSION;
attribs[nattribs++] = version.major_version;
attribs[nattribs++] = EGL_CONTEXT_MINOR_VERSION;
attribs[nattribs++] = version.minor_version;
}
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");
return false;
}
m_context = eglCreateContext(m_display, config.value(), share_context, attribs);
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"));
m_config = config.value();
m_version = version;
return true;
}
bool ContextEGL::CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current)
{
if (!CreateContext(version, share_context))
return false;
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))
{
Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError());
if (m_surface != EGL_NO_SURFACE)
{
eglDestroySurface(m_display, m_surface);
m_surface = EGL_NO_SURFACE;
}
eglDestroyContext(m_display, m_context);
m_context = EGL_NO_CONTEXT;
return false;
}
return true;
}
} // namespace GL
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include "context.h"
#include <glad/gl.h>
namespace GL {
class ContextEGL : public Context
{
public:
ContextEGL(const WindowInfo& wi);
~ContextEGL() override;
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try);
void* GetProcAddress(const char* name) override;
virtual bool ChangeSurface(const WindowInfo& new_wi) override;
virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
bool SwapBuffers() override;
bool MakeCurrent() override;
bool DoneCurrent() override;
bool SetSwapInterval(s32 interval) override;
virtual std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
protected:
virtual bool SetDisplay();
virtual EGLNativeWindowType GetNativeWindow(EGLConfig config);
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 CreateSurface();
bool CreatePBufferSurface();
bool CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const;
void DestroyContext();
void DestroySurface();
EGLDisplay m_display = EGL_NO_DISPLAY;
EGLSurface m_surface = EGL_NO_SURFACE;
EGLContext m_context = EGL_NO_CONTEXT;
EGLConfig m_config = {};
bool m_supports_surfaceless = false;
};
} // namespace GL
+86
View File
@@ -0,0 +1,86 @@
#include "context_egl_wayland.h"
#include "duckstation_log.h"
#include <dlfcn.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()
{
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<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
if (!context->LoadModule() || !context->Initialize(versions_to_try, num_versions_to_try))
return nullptr;
return context;
}
std::unique_ptr<Context> ContextEGLWayland::CreateSharedContext(const WindowInfo& wi)
{
std::unique_ptr<ContextEGLWayland> context = std::make_unique<ContextEGLWayland>(wi);
context->m_display = m_display;
if (!context->LoadModule() || !context->CreateContextAndSurface(m_version, m_context, false))
return nullptr;
return context;
}
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)
{
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);
if (!m_wl_window)
return {};
return reinterpret_cast<EGLNativeWindowType>(m_wl_window);
}
bool ContextEGLWayland::LoadModule()
{
m_wl_module = dlopen(WAYLAND_EGL_MODNAME, RTLD_NOW | RTLD_GLOBAL);
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)
{
Log_ErrorPrintf("Failed to load one or more functions from %s.", WAYLAND_EGL_MODNAME);
return false;
}
return true;
}
} // namespace GL
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include "context_egl.h"
#include <wayland-egl.h>
namespace GL {
class ContextEGLWayland final : public ContextEGL
{
public:
ContextEGLWayland(const WindowInfo& wi);
~ContextEGLWayland() override;
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try);
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
protected:
EGLNativeWindowType GetNativeWindow(EGLConfig config) override;
private:
bool LoadModule();
wl_egl_window* m_wl_window = nullptr;
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);
};
} // namespace GL
+69
View File
@@ -0,0 +1,69 @@
#include "context_egl_x11.h"
#include "duckstation_log.h"
Log_SetChannel(GL::ContextEGLX11);
namespace GL {
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)
{
std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi);
if (!context->Initialize(versions_to_try, num_versions_to_try))
return nullptr;
return context;
}
std::unique_ptr<Context> ContextEGLX11::CreateSharedContext(const WindowInfo& wi)
{
std::unique_ptr<ContextEGLX11> context = std::make_unique<ContextEGLX11>(wi);
context->m_display = m_display;
if (!context->CreateContextAndSurface(m_version, m_context, false))
return nullptr;
return context;
}
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)
{
X11InhibitErrors ei;
EGLint native_visual_id = 0;
if (!eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &native_visual_id))
{
Log_ErrorPrintf("Failed to get X11 visual ID");
return false;
}
XVisualInfo vi_query = {};
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)
{
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))
{
Log_ErrorPrintf("Faild to create X11 child window");
XFree(vi);
return false;
}
XFree(vi);
return static_cast<EGLNativeWindowType>(m_window.GetWindow());
}
} // namespace GL
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include "context_egl.h"
#include "x11_window.h"
namespace GL {
class ContextEGLX11 final : public ContextEGL
{
public:
ContextEGLX11(const WindowInfo& wi);
~ContextEGLX11() override;
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try);
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
protected:
EGLNativeWindowType GetNativeWindow(EGLConfig config) override;
private:
ALWAYS_INLINE Display* GetDisplay() const { return static_cast<Display*>(m_wi.display_connection); }
X11Window m_window;
};
} // namespace GL
+328
View File
@@ -0,0 +1,328 @@
#include "context_glx.h"
#include "duckstation_compat.h"
#include "duckstation_log.h"
#include <dlfcn.h>
Log_SetChannel(GL::ContextGLX);
namespace GL {
ContextGLX::ContextGLX(const WindowInfo& wi) : Context(wi) {}
ContextGLX::~ContextGLX()
{
if (glXGetCurrentContext() == m_context)
glXMakeCurrent(GetDisplay(), None, nullptr);
if (m_context)
glXDestroyContext(GetDisplay(), m_context);
if (m_vi)
XFree(m_vi);
if (m_libGL_handle)
dlclose(m_libGL_handle);
}
std::unique_ptr<Context> ContextGLX::Create(const WindowInfo& wi, const Version* 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;
return context;
}
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)
{
m_libGL_handle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL);
if (!m_libGL_handle)
{
Log_ErrorPrintf("Failed to load libGL.so: %s", dlerror());
return false;
}
}
const int screen = DefaultScreen(GetDisplay());
if (!gladLoadGLX(GetDisplay(), screen))
{
Log_ErrorPrintf("Loading GLAD GLX functions failed");
return false;
}
if (m_wi.type == WindowInfo::Type::X11)
{
if (!CreateWindow(screen))
return false;
}
else
{
Panic("Create pbuffer");
}
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))
{
m_version = cv;
return true;
}
else if (cv.profile != Profile::NoProfile && CreateVersionContext(cv, nullptr, true))
{
m_version = cv;
return true;
}
}
return false;
}
void* ContextGLX::GetProcAddress(const char* name)
{
return reinterpret_cast<void*>(glXGetProcAddress(reinterpret_cast<const GLubyte*>(name)));
}
bool ContextGLX::ChangeSurface(const WindowInfo& new_wi)
{
const bool was_current = (glXGetCurrentContext() == m_context);
if (was_current)
glXMakeCurrent(GetDisplay(), None, nullptr);
m_window.Destroy();
m_wi = new_wi;
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))
{
Log_ErrorPrintf("Failed to make context current again after surface change");
return false;
}
return true;
}
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()
{
glXSwapBuffers(GetDisplay(), GetDrawable());
return true;
}
bool ContextGLX::MakeCurrent()
{
return (glXMakeCurrent(GetDisplay(), GetDrawable(), m_context) == True);
}
bool ContextGLX::DoneCurrent()
{
return (glXMakeCurrent(GetDisplay(), None, nullptr) == True);
}
bool ContextGLX::SetSwapInterval(s32 interval)
{
if (GLAD_GLX_EXT_swap_control)
{
glXSwapIntervalEXT(GetDisplay(), GetDrawable(), interval);
return true;
}
else if (GLAD_GLX_MESA_swap_control)
{
return (glXSwapIntervalMESA(static_cast<u32>(std::max(interval, 0))) != 0);
}
else if (GLAD_GLX_SGI_swap_control)
{
return (glXSwapIntervalSGI(interval) != 0);
}
else
{
return false;
}
}
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)
{
const int screen = DefaultScreen(context->GetDisplay());
if (!context->CreateWindow(screen))
return nullptr;
}
else
{
Panic("Create pbuffer");
}
if (m_version.profile == Profile::NoProfile)
{
if (!context->CreateAnyContext(m_context, false))
return nullptr;
}
else
{
if (!context->CreateVersionContext(m_version, m_context, false))
return nullptr;
}
context->m_version = m_version;
return context;
}
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)
{
case WindowInfo::SurfaceFormat::RGB8:
attribs[nattribs++] = GLX_RED_SIZE;
attribs[nattribs++] = 8;
attribs[nattribs++] = GLX_GREEN_SIZE;
attribs[nattribs++] = 8;
attribs[nattribs++] = GLX_BLUE_SIZE;
attribs[nattribs++] = 8;
break;
case WindowInfo::SurfaceFormat::RGBA8:
attribs[nattribs++] = GLX_RED_SIZE;
attribs[nattribs++] = 8;
attribs[nattribs++] = GLX_GREEN_SIZE;
attribs[nattribs++] = 8;
attribs[nattribs++] = GLX_BLUE_SIZE;
attribs[nattribs++] = 8;
attribs[nattribs++] = GLX_ALPHA_SIZE;
attribs[nattribs++] = 8;
break;
case WindowInfo::SurfaceFormat::RGB565:
attribs[nattribs++] = GLX_RED_SIZE;
attribs[nattribs++] = 5;
attribs[nattribs++] = GLX_GREEN_SIZE;
attribs[nattribs++] = 6;
attribs[nattribs++] = GLX_BLUE_SIZE;
attribs[nattribs++] = 5;
break;
case WindowInfo::SurfaceFormat::Auto:
break;
default:
UnreachableCode();
break;
}
attribs[nattribs++] = None;
attribs[nattribs++] = 0;
int fbcount = 0;
GLXFBConfig* fbc = glXChooseFBConfig(GetDisplay(), screen, attribs, &fbcount);
if (!fbc || !fbcount)
{
Log_ErrorPrintf("glXChooseFBConfig() failed");
return false;
}
m_fb_config = *fbc;
XFree(fbc);
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)
{
Log_ErrorPrintf("glXGetVisualFromFBConfig() failed");
return false;
}
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)
{
X11InhibitErrors ie;
m_context = glXCreateContext(GetDisplay(), m_vi, share_context, True);
if (!m_context || ie.HadError())
{
Log_ErrorPrintf("glxCreateContext() failed");
return false;
}
if (make_current)
{
if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context))
{
Log_ErrorPrintf("glXMakeCurrent() failed");
return false;
}
}
return true;
}
bool ContextGLX::CreateVersionContext(const Version& version, GLXContext share_context, bool make_current)
{
// we need create context attribs
if (!GLAD_GLX_VERSION_1_3)
{
Log_ErrorPrint("Missing GLX version 1.3.");
return false;
}
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++] = GLX_CONTEXT_MAJOR_VERSION_ARB;
attribs[nattribs++] = version.major_version;
attribs[nattribs++] = GLX_CONTEXT_MINOR_VERSION_ARB;
attribs[nattribs++] = version.minor_version;
attribs[nattribs++] = None;
attribs[nattribs++] = 0;
X11InhibitErrors ie;
m_context = glXCreateContextAttribsARB(GetDisplay(), m_fb_config, share_context, True, attribs);
XSync(GetDisplay(), False);
if (ie.HadError())
m_context = nullptr;
if (!m_context)
return false;
if (make_current)
{
if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context))
{
Log_ErrorPrint("glXMakeCurrent() failed");
glXDestroyContext(GetDisplay(), m_context);
m_context = nullptr;
return false;
}
}
return true;
}
} // namespace GL
+44
View File
@@ -0,0 +1,44 @@
#pragma once
#include "context.h"
#include "../../glad/glad_glx.h"
#include "x11_window.h"
namespace GL {
class ContextGLX final : public Context
{
public:
ContextGLX(const WindowInfo& wi);
~ContextGLX() override;
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try);
void* GetProcAddress(const char* name) override;
bool ChangeSurface(const WindowInfo& new_wi) override;
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
bool SwapBuffers() override;
bool MakeCurrent() override;
bool DoneCurrent() override;
bool SetSwapInterval(s32 interval) override;
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()); }
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
bool CreateWindow(int screen);
bool CreateAnyContext(GLXContext share_context, bool make_current);
bool CreateVersionContext(const Version& version, GLXContext share_context, bool make_current);
GLXContext m_context = nullptr;
GLXFBConfig m_fb_config = {};
XVisualInfo* m_vi = nullptr;
X11Window m_window;
// GLAD releases its reference to libGL.so, so we need to maintain our own.
void* m_libGL_handle = nullptr;
};
} // namespace GL
+452
View File
@@ -0,0 +1,452 @@
#include "context_wgl.h"
#include "duckstation_compat.h"
#include "duckstation_log.h"
#include "duckstation_scoped_guard.h"
#include "loader.h"
Log_SetChannel(GL::ContextWGL);
// TODO: get rid of this
#pragma comment(lib, "opengl32.lib")
static void* GetProcAddressCallback(const char* name)
{
void* addr = reinterpret_cast<void*>(wglGetProcAddress(name));
if (addr)
return addr;
// try opengl32.dll
return reinterpret_cast<void*>(::GetProcAddress(GetModuleHandleA("opengl32.dll"), name));
}
namespace GL {
ContextWGL::ContextWGL(const WindowInfo& wi) : Context(wi) {}
ContextWGL::~ContextWGL()
{
if (wglGetCurrentContext() == m_rc)
wglMakeCurrent(m_dc, nullptr);
if (m_rc)
wglDeleteContext(m_rc);
ReleaseDC();
}
std::unique_ptr<Context> ContextWGL::Create(const WindowInfo& wi, const Version* 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;
return context;
}
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
{
Log_ErrorPrint("ContextWGL must always start with a valid surface.");
return false;
}
// Everything including core/ES requires a dummy profile to load the WGL extensions.
if (!CreateAnyContext(nullptr, true))
return false;
for (size_t i = 0; i < num_versions_to_try; i++)
{
const Version& cv = versions_to_try[i];
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))
{
m_version = cv;
return true;
}
}
return false;
}
void* ContextWGL::GetProcAddress(const char* name)
{
return GetProcAddressCallback(name);
}
bool ContextWGL::ChangeSurface(const WindowInfo& new_wi)
{
const bool was_current = (wglGetCurrentContext() == m_rc);
ReleaseDC();
m_wi = 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());
return false;
}
return true;
}
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()
{
return ::SwapBuffers(m_dc);
}
bool ContextWGL::MakeCurrent()
{
if (!wglMakeCurrent(m_dc, m_rc))
{
Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError());
return false;
}
return true;
}
bool ContextWGL::DoneCurrent()
{
return wglMakeCurrent(m_dc, nullptr);
}
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<ContextWGL> context = std::make_unique<ContextWGL>(wi);
if (wi.type == WindowInfo::Type::Win32)
{
if (!context->InitializeDC())
return nullptr;
}
else
{
Log_ErrorPrint("PBuffer not implemented");
return nullptr;
}
if (m_version.profile == Profile::NoProfile)
{
if (!context->CreateAnyContext(m_rc, false))
return nullptr;
}
else
{
if (!context->CreateVersionContext(m_version, m_rc, false))
return nullptr;
}
context->m_version = m_version;
return context;
}
HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd)
{
PIXELFORMATDESCRIPTOR pfd = {};
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.dwLayerMask = PFD_MAIN_PLANE;
pfd.cRedBits = 8;
pfd.cGreenBits = 8;
pfd.cBlueBits = 8;
pfd.cColorBits = 24;
HDC hDC = ::GetDC(hwnd);
if (!hDC)
{
Log_ErrorPrintf("GetDC() failed: 0x%08X", GetLastError());
return {};
}
if (!m_pixel_format.has_value())
{
const int pf = ChoosePixelFormat(hDC, &pfd);
if (pf == 0)
{
Log_ErrorPrintf("ChoosePixelFormat() failed: 0x%08X", GetLastError());
::ReleaseDC(hwnd, hDC);
return {};
}
m_pixel_format = pf;
}
if (!SetPixelFormat(hDC, m_pixel_format.value(), &pfd))
{
Log_ErrorPrintf("SetPixelFormat() failed: 0x%08X", GetLastError());
::ReleaseDC(hwnd, hDC);
return {};
}
return hDC;
}
bool ContextWGL::InitializeDC()
{
if (m_wi.type == WindowInfo::Type::Win32)
{
m_dc = GetDCAndSetPixelFormat(GetHWND());
if (!m_dc)
{
Log_ErrorPrint("Failed to get DC for window");
return false;
}
return true;
}
else if (m_wi.type == WindowInfo::Type::Surfaceless)
{
return CreatePBuffer();
}
else
{
Log_ErrorPrintf("Unknown window info type %u", static_cast<unsigned>(m_wi.type));
return false;
}
}
void ContextWGL::ReleaseDC()
{
if (m_pbuffer)
{
wglReleasePbufferDCARB(m_pbuffer, m_dc);
m_dc = {};
wglDestroyPbufferARB(m_pbuffer);
m_pbuffer = {};
::ReleaseDC(m_dummy_window, m_dummy_dc);
m_dummy_dc = {};
DestroyWindow(m_dummy_window);
m_dummy_window = {};
}
else if (m_dc)
{
::ReleaseDC(GetHWND(), m_dc);
m_dc = {};
}
}
bool ContextWGL::CreatePBuffer()
{
static bool window_class_registered = false;
static const wchar_t* window_class_name = L"ContextWGLPBuffer";
if (!window_class_registered)
{
WNDCLASSEXW wc = {};
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = 0;
wc.lpfnWndProc = DefWindowProcW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(nullptr);
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = window_class_name;
wc.hIconSm = NULL;
if (!RegisterClassExW(&wc))
{
Log_ErrorPrint("(ContextWGL::CreatePBuffer) RegisterClassExW() failed");
return false;
}
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)
{
Log_ErrorPrint("(ContextWGL::CreatePBuffer) CreateWindowEx() failed");
return false;
}
ScopedGuard hwnd_guard([hwnd]() { DestroyWindow(hwnd); });
HDC hdc = GetDCAndSetPixelFormat(hwnd);
if (!hdc)
return false;
ScopedGuard hdc_guard([hdc, hwnd]() { ::ReleaseDC(hwnd, hdc); });
static constexpr const int pb_attribs[] = {0, 0};
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)
{
Log_ErrorPrint("(ContextWGL::CreatePBuffer) wglCreatePbufferARB() failed");
return false;
}
ScopedGuard pbuffer_guard([pbuffer]() { wglDestroyPbufferARB(pbuffer); });
m_dc = wglGetPbufferDCARB(pbuffer);
if (!m_dc)
{
Log_ErrorPrint("(ContextWGL::CreatePbuffer) wglGetPbufferDCARB() failed");
return false;
}
m_dummy_window = hwnd;
m_dummy_dc = hdc;
m_pbuffer = pbuffer;
pbuffer_guard.Cancel();
hdc_guard.Cancel();
hwnd_guard.Cancel();
return true;
}
bool ContextWGL::CreateAnyContext(HGLRC share_context, bool make_current)
{
m_rc = wglCreateContext(m_dc);
if (!m_rc)
{
Log_ErrorPrintf("wglCreateContext() failed: 0x%08X", GetLastError());
return false;
}
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))
{
Log_ErrorPrint("Loading GLAD WGL functions failed");
return false;
}
}
if (share_context && !wglShareLists(share_context, m_rc))
{
Log_ErrorPrintf("wglShareLists() failed: 0x%08X", GetLastError());
return false;
}
return true;
}
bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_context, bool make_current)
{
// we need create context attribs
if (!GLAD_WGL_ARB_create_context)
{
Log_ErrorPrint("Missing GLAD_WGL_ARB_create_context.");
return false;
}
HGLRC new_rc;
if (version.profile == Profile::Core)
{
const int attribs[] = {WGL_CONTEXT_PROFILE_MASK_ARB,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
WGL_CONTEXT_MAJOR_VERSION_ARB,
version.major_version,
WGL_CONTEXT_MINOR_VERSION_ARB,
version.minor_version,
#ifdef _DEBUG
WGL_CONTEXT_FLAGS_ARB,
WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB,
#else
WGL_CONTEXT_FLAGS_ARB,
WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
#endif
0,
0};
new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs);
}
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))
{
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),
WGL_CONTEXT_MAJOR_VERSION_ARB,
version.major_version,
WGL_CONTEXT_MINOR_VERSION_ARB,
version.minor_version,
0,
0};
new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs);
}
else
{
Log_ErrorPrint("Unknown profile");
return false;
}
if (!new_rc)
return false;
// destroy and swap contexts
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))
{
Log_ErrorPrint("Loading GLAD WGL functions failed");
return false;
}
wglDeleteContext(m_rc);
}
m_rc = new_rc;
return true;
}
} // namespace GL
+53
View File
@@ -0,0 +1,53 @@
#pragma once
#include "windows_headers.h"
#include "context.h"
#include <glad/glad_wgl.h>
#include "loader.h"
#include <optional>
namespace GL {
class ContextWGL final : public Context
{
public:
ContextWGL(const WindowInfo& wi);
~ContextWGL() override;
static std::unique_ptr<Context> Create(const WindowInfo& wi, const Version* versions_to_try,
size_t num_versions_to_try);
void* GetProcAddress(const char* name) override;
bool ChangeSurface(const WindowInfo& new_wi) override;
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
bool SwapBuffers() override;
bool MakeCurrent() override;
bool DoneCurrent() override;
bool SetSwapInterval(s32 interval) override;
std::unique_ptr<Context> CreateSharedContext(const WindowInfo& wi) override;
private:
ALWAYS_INLINE HWND GetHWND() const { return static_cast<HWND>(m_wi.window_handle); }
HDC GetDCAndSetPixelFormat(HWND hwnd);
bool Initialize(const Version* versions_to_try, size_t num_versions_to_try);
bool InitializeDC();
void ReleaseDC();
bool CreatePBuffer();
bool CreateAnyContext(HGLRC share_context, bool make_current);
bool CreateVersionContext(const Version& version, HGLRC share_context, bool make_current);
HDC m_dc = {};
HGLRC m_rc = {};
// Can't change pixel format once it's set for a RC.
std::optional<int> m_pixel_format;
// Dummy window for creating a PBuffer off when we're surfaceless.
HWND m_dummy_window = {};
HDC m_dummy_dc = {};
HPBUFFERARB m_pbuffer = {};
};
} // namespace GL
+8
View File
@@ -0,0 +1,8 @@
#pragma once
// Fix glad.h including windows.h
#ifdef _WIN32
#include "windows_headers.h"
#endif
#include <glad/gl.h>
+101
View File
@@ -0,0 +1,101 @@
#include "x11_window.h"
#include "duckstation_log.h"
#include "duckstation_compat.h"
#include <cstdio>
Log_SetChannel(X11Window);
namespace GL {
X11Window::X11Window() = default;
X11Window::~X11Window()
{
Destroy();
}
bool X11Window::Create(Display* display, Window parent_window, const XVisualInfo* vi)
{
m_display = display;
m_parent_window = parent_window;
XSync(m_display, True);
XWindowAttributes parent_wa = {};
XGetWindowAttributes(m_display, m_parent_window, &parent_wa);
m_width = static_cast<u32>(parent_wa.width);
m_height = static_cast<u32>(parent_wa.height);
// Failed X calls terminate the process so no need to check for errors.
// We could swap the error handler out here as well.
m_colormap = XCreateColormap(m_display, m_parent_window, vi->visual, AllocNone);
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);
XMapWindow(m_display, m_window);
XSync(m_display, True);
return true;
}
void X11Window::Destroy()
{
if (m_window)
{
XUnmapWindow(m_display, m_window);
XDestroyWindow(m_display, m_window);
m_window = {};
}
if (m_colormap)
{
XFreeColormap(m_display, m_colormap);
m_colormap = {};
}
}
void X11Window::Resize(u32 width, u32 height)
{
if (width != 0 && height != 0)
{
m_width = width;
m_height = height;
}
else
{
XWindowAttributes parent_wa = {};
XGetWindowAttributes(m_display, m_parent_window, &parent_wa);
m_width = static_cast<u32>(parent_wa.width);
m_height = static_cast<u32>(parent_wa.height);
}
XResizeWindow(m_display, m_window, m_width, m_height);
}
static X11InhibitErrors* s_current_error_inhibiter;
X11InhibitErrors::X11InhibitErrors()
{
Assert(!s_current_error_inhibiter);
m_old_handler = XSetErrorHandler(ErrorHandler);
s_current_error_inhibiter = this;
}
X11InhibitErrors::~X11InhibitErrors()
{
Assert(s_current_error_inhibiter == this);
s_current_error_inhibiter = nullptr;
XSetErrorHandler(m_old_handler);
}
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);
s_current_error_inhibiter->m_had_error = true;
return 0;
}
} // namespace GL
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include "duckstation_compat.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
namespace GL {
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; }
bool Create(Display* display, Window parent_window, const XVisualInfo* vi);
void Destroy();
// Setting a width/height of 0 will use parent dimensions.
void Resize(u32 width = 0, u32 height = 0);
private:
Display* m_display = nullptr;
Window m_parent_window = {};
Window m_window = {};
Colormap m_colormap = {};
u32 m_width = 0;
u32 m_height = 0;
};
// Helper class for managing X errors
class X11InhibitErrors
{
public:
X11InhibitErrors();
~X11InhibitErrors();
ALWAYS_INLINE bool HadError() const { return m_had_error; }
private:
static int ErrorHandler(Display* display, XErrorEvent* ee);
XErrorHandler m_old_handler = {};
bool m_had_error = false;
};
} // namespace GL
+191
View File
@@ -0,0 +1,191 @@
#include "window_info.h"
#include "duckstation_log.h"
Log_SetChannel(WindowInfo);
#if defined(_WIN32)
#include "windows_headers.h"
#include <dwmapi.h>
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 bool load_tried = false;
if (!load_tried)
{
load_tried = true;
dwm_module = LoadLibrary(L"dwmapi.dll");
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"));
}
}
BOOL composition_enabled;
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 (ti.rateRefresh.uiNumerator == 0 || ti.rateRefresh.uiDenominator == 0)
return false;
*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)
{
HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
if (!mon)
return false;
MONITORINFOEXW mi = {};
mi.cbSize = sizeof(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)
{
*refresh_rate = static_cast<float>(dm.dmDisplayFrequency);
return true;
}
}
return false;
}
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);
}
#else
#ifdef USE_X11
#include "common/scoped_guard.h"
#include "gl/x11_window.h"
#include <X11/extensions/Xrandr.h>
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)
return false;
GL::X11InhibitErrors inhibiter;
XRRScreenResources* res = XRRGetScreenResources(display, window);
if (!res)
{
Log_ErrorPrint("XRRGetScreenResources() failed");
return false;
}
ScopedGuard res_guard([res]() { XRRFreeScreenResources(res); });
int num_monitors;
XRRMonitorInfo* mi = XRRGetMonitors(display, window, True, &num_monitors);
if (num_monitors < 0)
{
Log_ErrorPrint("XRRGetMonitors() failed");
return false;
}
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)
{
Log_ErrorPrint("Monitor has no outputs");
return false;
}
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)
{
Log_ErrorPrint("XRRGetOutputInfo() failed");
return false;
}
ScopedGuard oi_guard([oi]() { XRRFreeOutputInfo(oi); });
XRRCrtcInfo* ci = XRRGetCrtcInfo(display, res, oi->crtc);
if (!ci)
{
Log_ErrorPrint("XRRGetCrtcInfo() failed");
return false;
}
ScopedGuard ci_guard([ci]() { XRRFreeCrtcInfo(ci); });
XRRModeInfo* mode = nullptr;
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);
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);
return false;
}
*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)
{
#if defined(USE_X11)
if (wi.type == WindowInfo::Type::X11)
return GetRefreshRateFromXRandR(wi, refresh_rate);
#endif
return false;
}
#endif
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include "helpers.hpp"
// Contains the information required to create a graphics context in a window.
struct WindowInfo
{
enum class Type
{
Surfaceless,
Win32,
X11,
Wayland,
MacOS,
Android,
Display,
};
enum class SurfaceFormat
{
None,
Auto,
RGB8,
RGBA8,
RGB565,
Count
};
Type type = Type::Surfaceless;
void* display_connection = nullptr;
void* window_handle = nullptr;
u32 surface_width = 0;
u32 surface_height = 0;
float surface_refresh_rate = 0.0f;
float surface_scale = 1.0f;
SurfaceFormat surface_format = SurfaceFormat::RGB8;
// Needed for macOS.
#ifdef __APPLE__
void* surface_handle = nullptr;
#endif
static bool QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate);
};
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#ifndef NOMINMAX
#define NOMINMAX 1
#endif
// require vista+
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#include <windows.h>
#if defined(CreateDirectory)
#undef CreateDirectory
#endif
#if defined(CopyFile)
#undef CopyFile
#endif
#if defined(DeleteFile)
#undef DeleteFile
#endif
+9 -5
View File
@@ -1,7 +1,11 @@
add_library(glad STATIC
src/gl.c
include/glad/gl.h
include/KHR/khrplatform.h
)
set(GLAD_FILES src/gl.c include/KHR/khrplatform.h)
if(WIN32)
set(GLAD_FILES ${GLAD_FILES} src/glad_wgl.c)
elseif(NOT APPLE)
set(GLAD_FILES ${GLAD_FILES} src/glad_egl.c src/glad_glx.c)
endif()
add_library(glad STATIC ${GLAD_FILES})
target_include_directories(glad PUBLIC "include")
+169
View File
@@ -0,0 +1,169 @@
#ifndef __eglplatform_h_
#define __eglplatform_h_
/*
** Copyright 2007-2020 The Khronos Group Inc.
** SPDX-License-Identifier: Apache-2.0
*/
/* Platform-specific types and definitions for egl.h
*
* Adopters may modify khrplatform.h and this file to suit their platform.
* You are encouraged to submit all modifications to the Khronos group so that
* they can be included in future versions of this file. Please submit changes
* by filing an issue or pull request on the public Khronos EGL Registry, at
* https://www.github.com/KhronosGroup/EGL-Registry/
*/
#include <KHR/khrplatform.h>
/* Macros used in EGL function prototype declarations.
*
* EGL functions should be prototyped as:
*
* EGLAPI return-type EGLAPIENTRY eglFunction(arguments);
* typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments);
*
* KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h
*/
#ifndef EGLAPI
#define EGLAPI KHRONOS_APICALL
#endif
#ifndef EGLAPIENTRY
#define EGLAPIENTRY KHRONOS_APIENTRY
#endif
#define EGLAPIENTRYP EGLAPIENTRY*
/* The types NativeDisplayType, NativeWindowType, and NativePixmapType
* are aliases of window-system-dependent types, such as X Display * or
* Windows Device Context. They must be defined in platform-specific
* code below. The EGL-prefixed versions of Native*Type are the same
* types, renamed in EGL 1.3 so all types in the API start with "EGL".
*
* Khronos STRONGLY RECOMMENDS that you use the default definitions
* provided below, since these changes affect both binary and source
* portability of applications using EGL running on different EGL
* implementations.
*/
#if defined(EGL_NO_PLATFORM_SPECIFIC_TYPES)
typedef void *EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
typedef HWND EGLNativeWindowType;
#elif defined(__EMSCRIPTEN__)
typedef int EGLNativeDisplayType;
typedef int EGLNativePixmapType;
typedef int EGLNativeWindowType;
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
typedef int EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(WL_EGL_PLATFORM)
typedef struct wl_display *EGLNativeDisplayType;
typedef struct wl_egl_pixmap *EGLNativePixmapType;
typedef struct wl_egl_window *EGLNativeWindowType;
#elif defined(__GBM__)
typedef struct gbm_device *EGLNativeDisplayType;
typedef struct gbm_bo *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(__ANDROID__) || defined(ANDROID)
struct ANativeWindow;
struct egl_native_pixmap_t;
typedef void* EGLNativeDisplayType;
typedef struct egl_native_pixmap_t* EGLNativePixmapType;
typedef struct ANativeWindow* EGLNativeWindowType;
#elif defined(USE_OZONE)
typedef intptr_t EGLNativeDisplayType;
typedef intptr_t EGLNativePixmapType;
typedef intptr_t EGLNativeWindowType;
#elif defined(USE_X11)
/* X11 (tentative) */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
typedef Display *EGLNativeDisplayType;
typedef Pixmap EGLNativePixmapType;
typedef Window EGLNativeWindowType;
#elif defined(__unix__)
typedef void *EGLNativeDisplayType;
typedef khronos_uintptr_t EGLNativePixmapType;
typedef khronos_uintptr_t EGLNativeWindowType;
#elif defined(__APPLE__)
typedef int EGLNativeDisplayType;
typedef void *EGLNativePixmapType;
typedef void *EGLNativeWindowType;
#elif defined(__HAIKU__)
#include <kernel/image.h>
typedef void *EGLNativeDisplayType;
typedef khronos_uintptr_t EGLNativePixmapType;
typedef khronos_uintptr_t EGLNativeWindowType;
#elif defined(__Fuchsia__)
typedef void *EGLNativeDisplayType;
typedef khronos_uintptr_t EGLNativePixmapType;
typedef khronos_uintptr_t EGLNativeWindowType;
#else
#error "Platform not recognized"
#endif
/* EGL 1.2 types, renamed for consistency in EGL 1.3 */
typedef EGLNativeDisplayType NativeDisplayType;
typedef EGLNativePixmapType NativePixmapType;
typedef EGLNativeWindowType NativeWindowType;
/* Define EGLint. This must be a signed integral type large enough to contain
* all legal attribute names and values passed into and out of EGL, whether
* their type is boolean, bitmask, enumerant (symbolic constant), integer,
* handle, or other. While in general a 32-bit integer will suffice, if
* handles are 64 bit types, then EGLint should be defined as a signed 64-bit
* integer type.
*/
typedef khronos_int32_t EGLint;
/* C++ / C typecast macros for special EGL handle values */
#if defined(__cplusplus)
#define EGL_CAST(type, value) (static_cast<type>(value))
#else
#define EGL_CAST(type, value) ((type) (value))
#endif
#endif /* __eglplatform_h */
+18033 -13507
View File
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+10924 -8285
View File
File diff suppressed because one or more lines are too long
+45
View File
@@ -0,0 +1,45 @@
/*
EGL loader generated by glad 0.1.36 on Thu Sep 15 11:06:51 2022.
Language/Generator: C/C++
Specification: egl
APIs: egl=1.5
Profile: -
Extensions:
Loader: True
Local files: True
Omit khrplatform: False
Reproducible: False
Commandline:
--api="egl=1.5" --generator="c" --spec="egl" --local-files --extensions=""
Online:
https://glad.dav1d.de/#language=c&specification=egl&loader=on&api=egl%3D1.5
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glad/glad_egl.h>
int gladLoadEGL(void) {
return gladLoadEGLLoader((GLADloadproc)eglGetProcAddress);
}
static int find_extensionsEGL(void) {
return 1;
}
static void find_coreEGL(void) {
}
int gladLoadEGLLoader(GLADloadproc load) {
(void) load;
find_coreEGL();
if (!find_extensionsEGL()) return 0;
return 1;
}
+880
View File
@@ -0,0 +1,880 @@
/*
GLX loader generated by glad 0.1.36 on Sat Oct 8 13:52:35 2022.
Language/Generator: C/C++
Specification: glx
APIs: glx=1.4
Profile: -
Extensions:
GLX_3DFX_multisample,
GLX_AMD_gpu_association,
GLX_ARB_context_flush_control,
GLX_ARB_create_context,
GLX_ARB_create_context_no_error,
GLX_ARB_create_context_profile,
GLX_ARB_create_context_robustness,
GLX_ARB_fbconfig_float,
GLX_ARB_framebuffer_sRGB,
GLX_ARB_get_proc_address,
GLX_ARB_multisample,
GLX_ARB_robustness_application_isolation,
GLX_ARB_robustness_share_group_isolation,
GLX_ARB_vertex_buffer_object,
GLX_EXT_buffer_age,
GLX_EXT_context_priority,
GLX_EXT_create_context_es2_profile,
GLX_EXT_create_context_es_profile,
GLX_EXT_fbconfig_packed_float,
GLX_EXT_framebuffer_sRGB,
GLX_EXT_get_drawable_type,
GLX_EXT_import_context,
GLX_EXT_libglvnd,
GLX_EXT_no_config_context,
GLX_EXT_stereo_tree,
GLX_EXT_swap_control,
GLX_EXT_swap_control_tear,
GLX_EXT_texture_from_pixmap,
GLX_EXT_visual_info,
GLX_EXT_visual_rating,
GLX_INTEL_swap_event,
GLX_MESA_agp_offset,
GLX_MESA_copy_sub_buffer,
GLX_MESA_pixmap_colormap,
GLX_MESA_query_renderer,
GLX_MESA_release_buffers,
GLX_MESA_set_3dfx_mode,
GLX_MESA_swap_control,
GLX_NV_copy_buffer,
GLX_NV_copy_image,
GLX_NV_delay_before_swap,
GLX_NV_float_buffer,
GLX_NV_multigpu_context,
GLX_NV_multisample_coverage,
GLX_NV_present_video,
GLX_NV_robustness_video_memory_purge,
GLX_NV_swap_group,
GLX_NV_video_capture,
GLX_NV_video_out,
GLX_OML_swap_method,
GLX_OML_sync_control,
GLX_SGIS_blended_overlay,
GLX_SGIS_multisample,
GLX_SGIS_shared_multisample,
GLX_SGIX_dmbuffer,
GLX_SGIX_fbconfig,
GLX_SGIX_hyperpipe,
GLX_SGIX_pbuffer,
GLX_SGIX_swap_barrier,
GLX_SGIX_swap_group,
GLX_SGIX_video_resize,
GLX_SGIX_video_source,
GLX_SGIX_visual_select_group,
GLX_SGI_cushion,
GLX_SGI_make_current_read,
GLX_SGI_swap_control,
GLX_SGI_video_sync,
GLX_SUN_get_transparent_index
Loader: True
Local files: True
Omit khrplatform: False
Reproducible: False
Commandline:
--api="glx=1.4" --generator="c" --spec="glx" --local-files --extensions="GLX_3DFX_multisample,GLX_AMD_gpu_association,GLX_ARB_context_flush_control,GLX_ARB_create_context,GLX_ARB_create_context_no_error,GLX_ARB_create_context_profile,GLX_ARB_create_context_robustness,GLX_ARB_fbconfig_float,GLX_ARB_framebuffer_sRGB,GLX_ARB_get_proc_address,GLX_ARB_multisample,GLX_ARB_robustness_application_isolation,GLX_ARB_robustness_share_group_isolation,GLX_ARB_vertex_buffer_object,GLX_EXT_buffer_age,GLX_EXT_context_priority,GLX_EXT_create_context_es2_profile,GLX_EXT_create_context_es_profile,GLX_EXT_fbconfig_packed_float,GLX_EXT_framebuffer_sRGB,GLX_EXT_get_drawable_type,GLX_EXT_import_context,GLX_EXT_libglvnd,GLX_EXT_no_config_context,GLX_EXT_stereo_tree,GLX_EXT_swap_control,GLX_EXT_swap_control_tear,GLX_EXT_texture_from_pixmap,GLX_EXT_visual_info,GLX_EXT_visual_rating,GLX_INTEL_swap_event,GLX_MESA_agp_offset,GLX_MESA_copy_sub_buffer,GLX_MESA_pixmap_colormap,GLX_MESA_query_renderer,GLX_MESA_release_buffers,GLX_MESA_set_3dfx_mode,GLX_MESA_swap_control,GLX_NV_copy_buffer,GLX_NV_copy_image,GLX_NV_delay_before_swap,GLX_NV_float_buffer,GLX_NV_multigpu_context,GLX_NV_multisample_coverage,GLX_NV_present_video,GLX_NV_robustness_video_memory_purge,GLX_NV_swap_group,GLX_NV_video_capture,GLX_NV_video_out,GLX_OML_swap_method,GLX_OML_sync_control,GLX_SGIS_blended_overlay,GLX_SGIS_multisample,GLX_SGIS_shared_multisample,GLX_SGIX_dmbuffer,GLX_SGIX_fbconfig,GLX_SGIX_hyperpipe,GLX_SGIX_pbuffer,GLX_SGIX_swap_barrier,GLX_SGIX_swap_group,GLX_SGIX_video_resize,GLX_SGIX_video_source,GLX_SGIX_visual_select_group,GLX_SGI_cushion,GLX_SGI_make_current_read,GLX_SGI_swap_control,GLX_SGI_video_sync,GLX_SUN_get_transparent_index"
Online:
Too many extensions
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glad/glad_glx.h>
static void* get_proc(const char *namez);
#if defined(_WIN32) || defined(__CYGWIN__)
#ifndef _WINDOWS_
#undef APIENTRY
#endif
#include <windows.h>
static HMODULE libGL;
typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*);
static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
#ifdef _MSC_VER
#ifdef __has_include
#if __has_include(<winapifamily.h>)
#define HAVE_WINAPIFAMILY 1
#endif
#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
#define HAVE_WINAPIFAMILY 1
#endif
#endif
#ifdef HAVE_WINAPIFAMILY
#include <winapifamily.h>
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#define IS_UWP 1
#endif
#endif
static
int open_glx(void) {
#ifndef IS_UWP
libGL = LoadLibraryW(L"opengl32.dll");
if(libGL != NULL) {
void (* tmp)(void);
tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress");
gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp;
return gladGetProcAddressPtr != NULL;
}
#endif
return 0;
}
static
void close_glx(void) {
if(libGL != NULL) {
FreeLibrary((HMODULE) libGL);
libGL = NULL;
}
}
#else
#include <dlfcn.h>
static void* libGL;
#if !defined(__APPLE__) && !defined(__HAIKU__)
typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*);
static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
#endif
static
int open_glx(void) {
#ifdef __APPLE__
static const char *NAMES[] = {
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
};
#else
static const char *NAMES[] = {"libGL.so.1", "libGL.so"};
#endif
unsigned int index = 0;
for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) {
libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL);
if(libGL != NULL) {
#if defined(__APPLE__) || defined(__HAIKU__)
return 1;
#else
gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL,
"glXGetProcAddressARB");
return gladGetProcAddressPtr != NULL;
#endif
}
}
return 0;
}
static
void close_glx(void) {
if(libGL != NULL) {
dlclose(libGL);
libGL = NULL;
}
}
#endif
static
void* get_proc(const char *namez) {
void* result = NULL;
if(libGL == NULL) return NULL;
#if !defined(__APPLE__) && !defined(__HAIKU__)
if(gladGetProcAddressPtr != NULL) {
result = gladGetProcAddressPtr(namez);
}
#endif
if(result == NULL) {
#if defined(_WIN32) || defined(__CYGWIN__)
result = (void*)GetProcAddress((HMODULE) libGL, namez);
#else
result = dlsym(libGL, namez);
#endif
}
return result;
}
int gladLoadGLX(Display *dpy, int screen) {
int status = 0;
if(open_glx()) {
status = gladLoadGLXLoader((GLADloadproc)get_proc, dpy, screen);
}
return status;
}
void gladUnloadGLX(void) {
close_glx();
}
static Display *GLADGLXDisplay = 0;
static int GLADGLXscreen = 0;
static int get_exts(void) {
return 1;
}
static void free_exts(void) {
return;
}
static int has_ext(const char *ext) {
const char *terminator;
const char *loc;
const char *extensions;
if(!GLAD_GLX_VERSION_1_1)
return 0;
extensions = glXQueryExtensionsString(GLADGLXDisplay, GLADGLXscreen);
if(extensions == NULL || ext == NULL)
return 0;
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL)
break;
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\0'))
{
return 1;
}
extensions = terminator;
}
return 0;
}
int GLAD_GLX_VERSION_1_0 = 0;
int GLAD_GLX_VERSION_1_1 = 0;
int GLAD_GLX_VERSION_1_2 = 0;
int GLAD_GLX_VERSION_1_3 = 0;
int GLAD_GLX_VERSION_1_4 = 0;
PFNGLXCHOOSEFBCONFIGPROC glad_glXChooseFBConfig = NULL;
PFNGLXCHOOSEVISUALPROC glad_glXChooseVisual = NULL;
PFNGLXCOPYCONTEXTPROC glad_glXCopyContext = NULL;
PFNGLXCREATECONTEXTPROC glad_glXCreateContext = NULL;
PFNGLXCREATEGLXPIXMAPPROC glad_glXCreateGLXPixmap = NULL;
PFNGLXCREATENEWCONTEXTPROC glad_glXCreateNewContext = NULL;
PFNGLXCREATEPBUFFERPROC glad_glXCreatePbuffer = NULL;
PFNGLXCREATEPIXMAPPROC glad_glXCreatePixmap = NULL;
PFNGLXCREATEWINDOWPROC glad_glXCreateWindow = NULL;
PFNGLXDESTROYCONTEXTPROC glad_glXDestroyContext = NULL;
PFNGLXDESTROYGLXPIXMAPPROC glad_glXDestroyGLXPixmap = NULL;
PFNGLXDESTROYPBUFFERPROC glad_glXDestroyPbuffer = NULL;
PFNGLXDESTROYPIXMAPPROC glad_glXDestroyPixmap = NULL;
PFNGLXDESTROYWINDOWPROC glad_glXDestroyWindow = NULL;
PFNGLXGETCLIENTSTRINGPROC glad_glXGetClientString = NULL;
PFNGLXGETCONFIGPROC glad_glXGetConfig = NULL;
PFNGLXGETCURRENTCONTEXTPROC glad_glXGetCurrentContext = NULL;
PFNGLXGETCURRENTDISPLAYPROC glad_glXGetCurrentDisplay = NULL;
PFNGLXGETCURRENTDRAWABLEPROC glad_glXGetCurrentDrawable = NULL;
PFNGLXGETCURRENTREADDRAWABLEPROC glad_glXGetCurrentReadDrawable = NULL;
PFNGLXGETFBCONFIGATTRIBPROC glad_glXGetFBConfigAttrib = NULL;
PFNGLXGETFBCONFIGSPROC glad_glXGetFBConfigs = NULL;
PFNGLXGETPROCADDRESSPROC glad_glXGetProcAddress = NULL;
PFNGLXGETSELECTEDEVENTPROC glad_glXGetSelectedEvent = NULL;
PFNGLXGETVISUALFROMFBCONFIGPROC glad_glXGetVisualFromFBConfig = NULL;
PFNGLXISDIRECTPROC glad_glXIsDirect = NULL;
PFNGLXMAKECONTEXTCURRENTPROC glad_glXMakeContextCurrent = NULL;
PFNGLXMAKECURRENTPROC glad_glXMakeCurrent = NULL;
PFNGLXQUERYCONTEXTPROC glad_glXQueryContext = NULL;
PFNGLXQUERYDRAWABLEPROC glad_glXQueryDrawable = NULL;
PFNGLXQUERYEXTENSIONPROC glad_glXQueryExtension = NULL;
PFNGLXQUERYEXTENSIONSSTRINGPROC glad_glXQueryExtensionsString = NULL;
PFNGLXQUERYSERVERSTRINGPROC glad_glXQueryServerString = NULL;
PFNGLXQUERYVERSIONPROC glad_glXQueryVersion = NULL;
PFNGLXSELECTEVENTPROC glad_glXSelectEvent = NULL;
PFNGLXSWAPBUFFERSPROC glad_glXSwapBuffers = NULL;
PFNGLXUSEXFONTPROC glad_glXUseXFont = NULL;
PFNGLXWAITGLPROC glad_glXWaitGL = NULL;
PFNGLXWAITXPROC glad_glXWaitX = NULL;
int GLAD_GLX_3DFX_multisample = 0;
int GLAD_GLX_AMD_gpu_association = 0;
int GLAD_GLX_ARB_context_flush_control = 0;
int GLAD_GLX_ARB_create_context = 0;
int GLAD_GLX_ARB_create_context_no_error = 0;
int GLAD_GLX_ARB_create_context_profile = 0;
int GLAD_GLX_ARB_create_context_robustness = 0;
int GLAD_GLX_ARB_fbconfig_float = 0;
int GLAD_GLX_ARB_framebuffer_sRGB = 0;
int GLAD_GLX_ARB_get_proc_address = 0;
int GLAD_GLX_ARB_multisample = 0;
int GLAD_GLX_ARB_robustness_application_isolation = 0;
int GLAD_GLX_ARB_robustness_share_group_isolation = 0;
int GLAD_GLX_ARB_vertex_buffer_object = 0;
int GLAD_GLX_EXT_buffer_age = 0;
int GLAD_GLX_EXT_context_priority = 0;
int GLAD_GLX_EXT_create_context_es2_profile = 0;
int GLAD_GLX_EXT_create_context_es_profile = 0;
int GLAD_GLX_EXT_fbconfig_packed_float = 0;
int GLAD_GLX_EXT_framebuffer_sRGB = 0;
int GLAD_GLX_EXT_get_drawable_type = 0;
int GLAD_GLX_EXT_import_context = 0;
int GLAD_GLX_EXT_libglvnd = 0;
int GLAD_GLX_EXT_no_config_context = 0;
int GLAD_GLX_EXT_stereo_tree = 0;
int GLAD_GLX_EXT_swap_control = 0;
int GLAD_GLX_EXT_swap_control_tear = 0;
int GLAD_GLX_EXT_texture_from_pixmap = 0;
int GLAD_GLX_EXT_visual_info = 0;
int GLAD_GLX_EXT_visual_rating = 0;
int GLAD_GLX_INTEL_swap_event = 0;
int GLAD_GLX_MESA_agp_offset = 0;
int GLAD_GLX_MESA_copy_sub_buffer = 0;
int GLAD_GLX_MESA_pixmap_colormap = 0;
int GLAD_GLX_MESA_query_renderer = 0;
int GLAD_GLX_MESA_release_buffers = 0;
int GLAD_GLX_MESA_set_3dfx_mode = 0;
int GLAD_GLX_MESA_swap_control = 0;
int GLAD_GLX_NV_copy_buffer = 0;
int GLAD_GLX_NV_copy_image = 0;
int GLAD_GLX_NV_delay_before_swap = 0;
int GLAD_GLX_NV_float_buffer = 0;
int GLAD_GLX_NV_multigpu_context = 0;
int GLAD_GLX_NV_multisample_coverage = 0;
int GLAD_GLX_NV_present_video = 0;
int GLAD_GLX_NV_robustness_video_memory_purge = 0;
int GLAD_GLX_NV_swap_group = 0;
int GLAD_GLX_NV_video_capture = 0;
int GLAD_GLX_NV_video_out = 0;
int GLAD_GLX_OML_swap_method = 0;
int GLAD_GLX_OML_sync_control = 0;
int GLAD_GLX_SGIS_blended_overlay = 0;
int GLAD_GLX_SGIS_multisample = 0;
int GLAD_GLX_SGIS_shared_multisample = 0;
int GLAD_GLX_SGIX_dmbuffer = 0;
int GLAD_GLX_SGIX_fbconfig = 0;
int GLAD_GLX_SGIX_hyperpipe = 0;
int GLAD_GLX_SGIX_pbuffer = 0;
int GLAD_GLX_SGIX_swap_barrier = 0;
int GLAD_GLX_SGIX_swap_group = 0;
int GLAD_GLX_SGIX_video_resize = 0;
int GLAD_GLX_SGIX_video_source = 0;
int GLAD_GLX_SGIX_visual_select_group = 0;
int GLAD_GLX_SGI_cushion = 0;
int GLAD_GLX_SGI_make_current_read = 0;
int GLAD_GLX_SGI_swap_control = 0;
int GLAD_GLX_SGI_video_sync = 0;
int GLAD_GLX_SUN_get_transparent_index = 0;
PFNGLXGETGPUIDSAMDPROC glad_glXGetGPUIDsAMD = NULL;
PFNGLXGETGPUINFOAMDPROC glad_glXGetGPUInfoAMD = NULL;
PFNGLXGETCONTEXTGPUIDAMDPROC glad_glXGetContextGPUIDAMD = NULL;
PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC glad_glXCreateAssociatedContextAMD = NULL;
PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC glad_glXCreateAssociatedContextAttribsAMD = NULL;
PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC glad_glXDeleteAssociatedContextAMD = NULL;
PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC glad_glXMakeAssociatedContextCurrentAMD = NULL;
PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC glad_glXGetCurrentAssociatedContextAMD = NULL;
PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC glad_glXBlitContextFramebufferAMD = NULL;
PFNGLXCREATECONTEXTATTRIBSARBPROC glad_glXCreateContextAttribsARB = NULL;
PFNGLXGETPROCADDRESSARBPROC glad_glXGetProcAddressARB = NULL;
PFNGLXGETCURRENTDISPLAYEXTPROC glad_glXGetCurrentDisplayEXT = NULL;
PFNGLXQUERYCONTEXTINFOEXTPROC glad_glXQueryContextInfoEXT = NULL;
PFNGLXGETCONTEXTIDEXTPROC glad_glXGetContextIDEXT = NULL;
PFNGLXIMPORTCONTEXTEXTPROC glad_glXImportContextEXT = NULL;
PFNGLXFREECONTEXTEXTPROC glad_glXFreeContextEXT = NULL;
PFNGLXSWAPINTERVALEXTPROC glad_glXSwapIntervalEXT = NULL;
PFNGLXBINDTEXIMAGEEXTPROC glad_glXBindTexImageEXT = NULL;
PFNGLXRELEASETEXIMAGEEXTPROC glad_glXReleaseTexImageEXT = NULL;
PFNGLXGETAGPOFFSETMESAPROC glad_glXGetAGPOffsetMESA = NULL;
PFNGLXCOPYSUBBUFFERMESAPROC glad_glXCopySubBufferMESA = NULL;
PFNGLXCREATEGLXPIXMAPMESAPROC glad_glXCreateGLXPixmapMESA = NULL;
PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC glad_glXQueryCurrentRendererIntegerMESA = NULL;
PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC glad_glXQueryCurrentRendererStringMESA = NULL;
PFNGLXQUERYRENDERERINTEGERMESAPROC glad_glXQueryRendererIntegerMESA = NULL;
PFNGLXQUERYRENDERERSTRINGMESAPROC glad_glXQueryRendererStringMESA = NULL;
PFNGLXRELEASEBUFFERSMESAPROC glad_glXReleaseBuffersMESA = NULL;
PFNGLXSET3DFXMODEMESAPROC glad_glXSet3DfxModeMESA = NULL;
PFNGLXGETSWAPINTERVALMESAPROC glad_glXGetSwapIntervalMESA = NULL;
PFNGLXSWAPINTERVALMESAPROC glad_glXSwapIntervalMESA = NULL;
PFNGLXCOPYBUFFERSUBDATANVPROC glad_glXCopyBufferSubDataNV = NULL;
PFNGLXNAMEDCOPYBUFFERSUBDATANVPROC glad_glXNamedCopyBufferSubDataNV = NULL;
PFNGLXCOPYIMAGESUBDATANVPROC glad_glXCopyImageSubDataNV = NULL;
PFNGLXDELAYBEFORESWAPNVPROC glad_glXDelayBeforeSwapNV = NULL;
PFNGLXENUMERATEVIDEODEVICESNVPROC glad_glXEnumerateVideoDevicesNV = NULL;
PFNGLXBINDVIDEODEVICENVPROC glad_glXBindVideoDeviceNV = NULL;
PFNGLXJOINSWAPGROUPNVPROC glad_glXJoinSwapGroupNV = NULL;
PFNGLXBINDSWAPBARRIERNVPROC glad_glXBindSwapBarrierNV = NULL;
PFNGLXQUERYSWAPGROUPNVPROC glad_glXQuerySwapGroupNV = NULL;
PFNGLXQUERYMAXSWAPGROUPSNVPROC glad_glXQueryMaxSwapGroupsNV = NULL;
PFNGLXQUERYFRAMECOUNTNVPROC glad_glXQueryFrameCountNV = NULL;
PFNGLXRESETFRAMECOUNTNVPROC glad_glXResetFrameCountNV = NULL;
PFNGLXBINDVIDEOCAPTUREDEVICENVPROC glad_glXBindVideoCaptureDeviceNV = NULL;
PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC glad_glXEnumerateVideoCaptureDevicesNV = NULL;
PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC glad_glXLockVideoCaptureDeviceNV = NULL;
PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC glad_glXQueryVideoCaptureDeviceNV = NULL;
PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC glad_glXReleaseVideoCaptureDeviceNV = NULL;
PFNGLXGETVIDEODEVICENVPROC glad_glXGetVideoDeviceNV = NULL;
PFNGLXRELEASEVIDEODEVICENVPROC glad_glXReleaseVideoDeviceNV = NULL;
PFNGLXBINDVIDEOIMAGENVPROC glad_glXBindVideoImageNV = NULL;
PFNGLXRELEASEVIDEOIMAGENVPROC glad_glXReleaseVideoImageNV = NULL;
PFNGLXSENDPBUFFERTOVIDEONVPROC glad_glXSendPbufferToVideoNV = NULL;
PFNGLXGETVIDEOINFONVPROC glad_glXGetVideoInfoNV = NULL;
PFNGLXGETSYNCVALUESOMLPROC glad_glXGetSyncValuesOML = NULL;
PFNGLXGETMSCRATEOMLPROC glad_glXGetMscRateOML = NULL;
PFNGLXSWAPBUFFERSMSCOMLPROC glad_glXSwapBuffersMscOML = NULL;
PFNGLXWAITFORMSCOMLPROC glad_glXWaitForMscOML = NULL;
PFNGLXWAITFORSBCOMLPROC glad_glXWaitForSbcOML = NULL;
#ifdef _DM_BUFFER_H_
PFNGLXASSOCIATEDMPBUFFERSGIXPROC glad_glXAssociateDMPbufferSGIX = NULL;
#endif
PFNGLXGETFBCONFIGATTRIBSGIXPROC glad_glXGetFBConfigAttribSGIX = NULL;
PFNGLXCHOOSEFBCONFIGSGIXPROC glad_glXChooseFBConfigSGIX = NULL;
PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC glad_glXCreateGLXPixmapWithConfigSGIX = NULL;
PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC glad_glXCreateContextWithConfigSGIX = NULL;
PFNGLXGETVISUALFROMFBCONFIGSGIXPROC glad_glXGetVisualFromFBConfigSGIX = NULL;
PFNGLXGETFBCONFIGFROMVISUALSGIXPROC glad_glXGetFBConfigFromVisualSGIX = NULL;
PFNGLXQUERYHYPERPIPENETWORKSGIXPROC glad_glXQueryHyperpipeNetworkSGIX = NULL;
PFNGLXHYPERPIPECONFIGSGIXPROC glad_glXHyperpipeConfigSGIX = NULL;
PFNGLXQUERYHYPERPIPECONFIGSGIXPROC glad_glXQueryHyperpipeConfigSGIX = NULL;
PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC glad_glXDestroyHyperpipeConfigSGIX = NULL;
PFNGLXBINDHYPERPIPESGIXPROC glad_glXBindHyperpipeSGIX = NULL;
PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC glad_glXQueryHyperpipeBestAttribSGIX = NULL;
PFNGLXHYPERPIPEATTRIBSGIXPROC glad_glXHyperpipeAttribSGIX = NULL;
PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC glad_glXQueryHyperpipeAttribSGIX = NULL;
PFNGLXCREATEGLXPBUFFERSGIXPROC glad_glXCreateGLXPbufferSGIX = NULL;
PFNGLXDESTROYGLXPBUFFERSGIXPROC glad_glXDestroyGLXPbufferSGIX = NULL;
PFNGLXQUERYGLXPBUFFERSGIXPROC glad_glXQueryGLXPbufferSGIX = NULL;
PFNGLXSELECTEVENTSGIXPROC glad_glXSelectEventSGIX = NULL;
PFNGLXGETSELECTEDEVENTSGIXPROC glad_glXGetSelectedEventSGIX = NULL;
PFNGLXBINDSWAPBARRIERSGIXPROC glad_glXBindSwapBarrierSGIX = NULL;
PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC glad_glXQueryMaxSwapBarriersSGIX = NULL;
PFNGLXJOINSWAPGROUPSGIXPROC glad_glXJoinSwapGroupSGIX = NULL;
PFNGLXBINDCHANNELTOWINDOWSGIXPROC glad_glXBindChannelToWindowSGIX = NULL;
PFNGLXCHANNELRECTSGIXPROC glad_glXChannelRectSGIX = NULL;
PFNGLXQUERYCHANNELRECTSGIXPROC glad_glXQueryChannelRectSGIX = NULL;
PFNGLXQUERYCHANNELDELTASSGIXPROC glad_glXQueryChannelDeltasSGIX = NULL;
PFNGLXCHANNELRECTSYNCSGIXPROC glad_glXChannelRectSyncSGIX = NULL;
#ifdef _VL_H_
PFNGLXCREATEGLXVIDEOSOURCESGIXPROC glad_glXCreateGLXVideoSourceSGIX = NULL;
PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC glad_glXDestroyGLXVideoSourceSGIX = NULL;
#endif
PFNGLXCUSHIONSGIPROC glad_glXCushionSGI = NULL;
PFNGLXMAKECURRENTREADSGIPROC glad_glXMakeCurrentReadSGI = NULL;
PFNGLXGETCURRENTREADDRAWABLESGIPROC glad_glXGetCurrentReadDrawableSGI = NULL;
PFNGLXSWAPINTERVALSGIPROC glad_glXSwapIntervalSGI = NULL;
PFNGLXGETVIDEOSYNCSGIPROC glad_glXGetVideoSyncSGI = NULL;
PFNGLXWAITVIDEOSYNCSGIPROC glad_glXWaitVideoSyncSGI = NULL;
PFNGLXGETTRANSPARENTINDEXSUNPROC glad_glXGetTransparentIndexSUN = NULL;
static void load_GLX_VERSION_1_0(GLADloadproc load) {
if(!GLAD_GLX_VERSION_1_0) return;
glad_glXChooseVisual = (PFNGLXCHOOSEVISUALPROC)load("glXChooseVisual");
glad_glXCreateContext = (PFNGLXCREATECONTEXTPROC)load("glXCreateContext");
glad_glXDestroyContext = (PFNGLXDESTROYCONTEXTPROC)load("glXDestroyContext");
glad_glXMakeCurrent = (PFNGLXMAKECURRENTPROC)load("glXMakeCurrent");
glad_glXCopyContext = (PFNGLXCOPYCONTEXTPROC)load("glXCopyContext");
glad_glXSwapBuffers = (PFNGLXSWAPBUFFERSPROC)load("glXSwapBuffers");
glad_glXCreateGLXPixmap = (PFNGLXCREATEGLXPIXMAPPROC)load("glXCreateGLXPixmap");
glad_glXDestroyGLXPixmap = (PFNGLXDESTROYGLXPIXMAPPROC)load("glXDestroyGLXPixmap");
glad_glXQueryExtension = (PFNGLXQUERYEXTENSIONPROC)load("glXQueryExtension");
glad_glXQueryVersion = (PFNGLXQUERYVERSIONPROC)load("glXQueryVersion");
glad_glXIsDirect = (PFNGLXISDIRECTPROC)load("glXIsDirect");
glad_glXGetConfig = (PFNGLXGETCONFIGPROC)load("glXGetConfig");
glad_glXGetCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC)load("glXGetCurrentContext");
glad_glXGetCurrentDrawable = (PFNGLXGETCURRENTDRAWABLEPROC)load("glXGetCurrentDrawable");
glad_glXWaitGL = (PFNGLXWAITGLPROC)load("glXWaitGL");
glad_glXWaitX = (PFNGLXWAITXPROC)load("glXWaitX");
glad_glXUseXFont = (PFNGLXUSEXFONTPROC)load("glXUseXFont");
}
static void load_GLX_VERSION_1_1(GLADloadproc load) {
if(!GLAD_GLX_VERSION_1_1) return;
glad_glXQueryExtensionsString = (PFNGLXQUERYEXTENSIONSSTRINGPROC)load("glXQueryExtensionsString");
glad_glXQueryServerString = (PFNGLXQUERYSERVERSTRINGPROC)load("glXQueryServerString");
glad_glXGetClientString = (PFNGLXGETCLIENTSTRINGPROC)load("glXGetClientString");
}
static void load_GLX_VERSION_1_2(GLADloadproc load) {
if(!GLAD_GLX_VERSION_1_2) return;
glad_glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC)load("glXGetCurrentDisplay");
}
static void load_GLX_VERSION_1_3(GLADloadproc load) {
if(!GLAD_GLX_VERSION_1_3) return;
glad_glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC)load("glXGetFBConfigs");
glad_glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)load("glXChooseFBConfig");
glad_glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)load("glXGetFBConfigAttrib");
glad_glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)load("glXGetVisualFromFBConfig");
glad_glXCreateWindow = (PFNGLXCREATEWINDOWPROC)load("glXCreateWindow");
glad_glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC)load("glXDestroyWindow");
glad_glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC)load("glXCreatePixmap");
glad_glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC)load("glXDestroyPixmap");
glad_glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC)load("glXCreatePbuffer");
glad_glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC)load("glXDestroyPbuffer");
glad_glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC)load("glXQueryDrawable");
glad_glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC)load("glXCreateNewContext");
glad_glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC)load("glXMakeContextCurrent");
glad_glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC)load("glXGetCurrentReadDrawable");
glad_glXQueryContext = (PFNGLXQUERYCONTEXTPROC)load("glXQueryContext");
glad_glXSelectEvent = (PFNGLXSELECTEVENTPROC)load("glXSelectEvent");
glad_glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC)load("glXGetSelectedEvent");
}
static void load_GLX_VERSION_1_4(GLADloadproc load) {
if(!GLAD_GLX_VERSION_1_4) return;
glad_glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC)load("glXGetProcAddress");
}
static void load_GLX_AMD_gpu_association(GLADloadproc load) {
if(!GLAD_GLX_AMD_gpu_association) return;
glad_glXGetGPUIDsAMD = (PFNGLXGETGPUIDSAMDPROC)load("glXGetGPUIDsAMD");
glad_glXGetGPUInfoAMD = (PFNGLXGETGPUINFOAMDPROC)load("glXGetGPUInfoAMD");
glad_glXGetContextGPUIDAMD = (PFNGLXGETCONTEXTGPUIDAMDPROC)load("glXGetContextGPUIDAMD");
glad_glXCreateAssociatedContextAMD = (PFNGLXCREATEASSOCIATEDCONTEXTAMDPROC)load("glXCreateAssociatedContextAMD");
glad_glXCreateAssociatedContextAttribsAMD = (PFNGLXCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)load("glXCreateAssociatedContextAttribsAMD");
glad_glXDeleteAssociatedContextAMD = (PFNGLXDELETEASSOCIATEDCONTEXTAMDPROC)load("glXDeleteAssociatedContextAMD");
glad_glXMakeAssociatedContextCurrentAMD = (PFNGLXMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)load("glXMakeAssociatedContextCurrentAMD");
glad_glXGetCurrentAssociatedContextAMD = (PFNGLXGETCURRENTASSOCIATEDCONTEXTAMDPROC)load("glXGetCurrentAssociatedContextAMD");
glad_glXBlitContextFramebufferAMD = (PFNGLXBLITCONTEXTFRAMEBUFFERAMDPROC)load("glXBlitContextFramebufferAMD");
}
static void load_GLX_ARB_create_context(GLADloadproc load) {
if(!GLAD_GLX_ARB_create_context) return;
glad_glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)load("glXCreateContextAttribsARB");
}
static void load_GLX_ARB_get_proc_address(GLADloadproc load) {
if(!GLAD_GLX_ARB_get_proc_address) return;
glad_glXGetProcAddressARB = (PFNGLXGETPROCADDRESSARBPROC)load("glXGetProcAddressARB");
}
static void load_GLX_EXT_import_context(GLADloadproc load) {
if(!GLAD_GLX_EXT_import_context) return;
glad_glXGetCurrentDisplayEXT = (PFNGLXGETCURRENTDISPLAYEXTPROC)load("glXGetCurrentDisplayEXT");
glad_glXQueryContextInfoEXT = (PFNGLXQUERYCONTEXTINFOEXTPROC)load("glXQueryContextInfoEXT");
glad_glXGetContextIDEXT = (PFNGLXGETCONTEXTIDEXTPROC)load("glXGetContextIDEXT");
glad_glXImportContextEXT = (PFNGLXIMPORTCONTEXTEXTPROC)load("glXImportContextEXT");
glad_glXFreeContextEXT = (PFNGLXFREECONTEXTEXTPROC)load("glXFreeContextEXT");
}
static void load_GLX_EXT_swap_control(GLADloadproc load) {
if(!GLAD_GLX_EXT_swap_control) return;
glad_glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)load("glXSwapIntervalEXT");
}
static void load_GLX_EXT_texture_from_pixmap(GLADloadproc load) {
if(!GLAD_GLX_EXT_texture_from_pixmap) return;
glad_glXBindTexImageEXT = (PFNGLXBINDTEXIMAGEEXTPROC)load("glXBindTexImageEXT");
glad_glXReleaseTexImageEXT = (PFNGLXRELEASETEXIMAGEEXTPROC)load("glXReleaseTexImageEXT");
}
static void load_GLX_MESA_agp_offset(GLADloadproc load) {
if(!GLAD_GLX_MESA_agp_offset) return;
glad_glXGetAGPOffsetMESA = (PFNGLXGETAGPOFFSETMESAPROC)load("glXGetAGPOffsetMESA");
}
static void load_GLX_MESA_copy_sub_buffer(GLADloadproc load) {
if(!GLAD_GLX_MESA_copy_sub_buffer) return;
glad_glXCopySubBufferMESA = (PFNGLXCOPYSUBBUFFERMESAPROC)load("glXCopySubBufferMESA");
}
static void load_GLX_MESA_pixmap_colormap(GLADloadproc load) {
if(!GLAD_GLX_MESA_pixmap_colormap) return;
glad_glXCreateGLXPixmapMESA = (PFNGLXCREATEGLXPIXMAPMESAPROC)load("glXCreateGLXPixmapMESA");
}
static void load_GLX_MESA_query_renderer(GLADloadproc load) {
if(!GLAD_GLX_MESA_query_renderer) return;
glad_glXQueryCurrentRendererIntegerMESA = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC)load("glXQueryCurrentRendererIntegerMESA");
glad_glXQueryCurrentRendererStringMESA = (PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC)load("glXQueryCurrentRendererStringMESA");
glad_glXQueryRendererIntegerMESA = (PFNGLXQUERYRENDERERINTEGERMESAPROC)load("glXQueryRendererIntegerMESA");
glad_glXQueryRendererStringMESA = (PFNGLXQUERYRENDERERSTRINGMESAPROC)load("glXQueryRendererStringMESA");
}
static void load_GLX_MESA_release_buffers(GLADloadproc load) {
if(!GLAD_GLX_MESA_release_buffers) return;
glad_glXReleaseBuffersMESA = (PFNGLXRELEASEBUFFERSMESAPROC)load("glXReleaseBuffersMESA");
}
static void load_GLX_MESA_set_3dfx_mode(GLADloadproc load) {
if(!GLAD_GLX_MESA_set_3dfx_mode) return;
glad_glXSet3DfxModeMESA = (PFNGLXSET3DFXMODEMESAPROC)load("glXSet3DfxModeMESA");
}
static void load_GLX_MESA_swap_control(GLADloadproc load) {
if(!GLAD_GLX_MESA_swap_control) return;
glad_glXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC)load("glXGetSwapIntervalMESA");
glad_glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)load("glXSwapIntervalMESA");
}
static void load_GLX_NV_copy_buffer(GLADloadproc load) {
if(!GLAD_GLX_NV_copy_buffer) return;
glad_glXCopyBufferSubDataNV = (PFNGLXCOPYBUFFERSUBDATANVPROC)load("glXCopyBufferSubDataNV");
glad_glXNamedCopyBufferSubDataNV = (PFNGLXNAMEDCOPYBUFFERSUBDATANVPROC)load("glXNamedCopyBufferSubDataNV");
}
static void load_GLX_NV_copy_image(GLADloadproc load) {
if(!GLAD_GLX_NV_copy_image) return;
glad_glXCopyImageSubDataNV = (PFNGLXCOPYIMAGESUBDATANVPROC)load("glXCopyImageSubDataNV");
}
static void load_GLX_NV_delay_before_swap(GLADloadproc load) {
if(!GLAD_GLX_NV_delay_before_swap) return;
glad_glXDelayBeforeSwapNV = (PFNGLXDELAYBEFORESWAPNVPROC)load("glXDelayBeforeSwapNV");
}
static void load_GLX_NV_present_video(GLADloadproc load) {
if(!GLAD_GLX_NV_present_video) return;
glad_glXEnumerateVideoDevicesNV = (PFNGLXENUMERATEVIDEODEVICESNVPROC)load("glXEnumerateVideoDevicesNV");
glad_glXBindVideoDeviceNV = (PFNGLXBINDVIDEODEVICENVPROC)load("glXBindVideoDeviceNV");
}
static void load_GLX_NV_swap_group(GLADloadproc load) {
if(!GLAD_GLX_NV_swap_group) return;
glad_glXJoinSwapGroupNV = (PFNGLXJOINSWAPGROUPNVPROC)load("glXJoinSwapGroupNV");
glad_glXBindSwapBarrierNV = (PFNGLXBINDSWAPBARRIERNVPROC)load("glXBindSwapBarrierNV");
glad_glXQuerySwapGroupNV = (PFNGLXQUERYSWAPGROUPNVPROC)load("glXQuerySwapGroupNV");
glad_glXQueryMaxSwapGroupsNV = (PFNGLXQUERYMAXSWAPGROUPSNVPROC)load("glXQueryMaxSwapGroupsNV");
glad_glXQueryFrameCountNV = (PFNGLXQUERYFRAMECOUNTNVPROC)load("glXQueryFrameCountNV");
glad_glXResetFrameCountNV = (PFNGLXRESETFRAMECOUNTNVPROC)load("glXResetFrameCountNV");
}
static void load_GLX_NV_video_capture(GLADloadproc load) {
if(!GLAD_GLX_NV_video_capture) return;
glad_glXBindVideoCaptureDeviceNV = (PFNGLXBINDVIDEOCAPTUREDEVICENVPROC)load("glXBindVideoCaptureDeviceNV");
glad_glXEnumerateVideoCaptureDevicesNV = (PFNGLXENUMERATEVIDEOCAPTUREDEVICESNVPROC)load("glXEnumerateVideoCaptureDevicesNV");
glad_glXLockVideoCaptureDeviceNV = (PFNGLXLOCKVIDEOCAPTUREDEVICENVPROC)load("glXLockVideoCaptureDeviceNV");
glad_glXQueryVideoCaptureDeviceNV = (PFNGLXQUERYVIDEOCAPTUREDEVICENVPROC)load("glXQueryVideoCaptureDeviceNV");
glad_glXReleaseVideoCaptureDeviceNV = (PFNGLXRELEASEVIDEOCAPTUREDEVICENVPROC)load("glXReleaseVideoCaptureDeviceNV");
}
static void load_GLX_NV_video_out(GLADloadproc load) {
if(!GLAD_GLX_NV_video_out) return;
glad_glXGetVideoDeviceNV = (PFNGLXGETVIDEODEVICENVPROC)load("glXGetVideoDeviceNV");
glad_glXReleaseVideoDeviceNV = (PFNGLXRELEASEVIDEODEVICENVPROC)load("glXReleaseVideoDeviceNV");
glad_glXBindVideoImageNV = (PFNGLXBINDVIDEOIMAGENVPROC)load("glXBindVideoImageNV");
glad_glXReleaseVideoImageNV = (PFNGLXRELEASEVIDEOIMAGENVPROC)load("glXReleaseVideoImageNV");
glad_glXSendPbufferToVideoNV = (PFNGLXSENDPBUFFERTOVIDEONVPROC)load("glXSendPbufferToVideoNV");
glad_glXGetVideoInfoNV = (PFNGLXGETVIDEOINFONVPROC)load("glXGetVideoInfoNV");
}
static void load_GLX_OML_sync_control(GLADloadproc load) {
if(!GLAD_GLX_OML_sync_control) return;
glad_glXGetSyncValuesOML = (PFNGLXGETSYNCVALUESOMLPROC)load("glXGetSyncValuesOML");
glad_glXGetMscRateOML = (PFNGLXGETMSCRATEOMLPROC)load("glXGetMscRateOML");
glad_glXSwapBuffersMscOML = (PFNGLXSWAPBUFFERSMSCOMLPROC)load("glXSwapBuffersMscOML");
glad_glXWaitForMscOML = (PFNGLXWAITFORMSCOMLPROC)load("glXWaitForMscOML");
glad_glXWaitForSbcOML = (PFNGLXWAITFORSBCOMLPROC)load("glXWaitForSbcOML");
}
static void load_GLX_SGIX_dmbuffer(GLADloadproc load) {
if(!GLAD_GLX_SGIX_dmbuffer) return;
#ifdef _DM_BUFFER_H_
glad_glXAssociateDMPbufferSGIX = (PFNGLXASSOCIATEDMPBUFFERSGIXPROC)load("glXAssociateDMPbufferSGIX");
#else
(void)load;
#endif
}
static void load_GLX_SGIX_fbconfig(GLADloadproc load) {
if(!GLAD_GLX_SGIX_fbconfig) return;
glad_glXGetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC)load("glXGetFBConfigAttribSGIX");
glad_glXChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC)load("glXChooseFBConfigSGIX");
glad_glXCreateGLXPixmapWithConfigSGIX = (PFNGLXCREATEGLXPIXMAPWITHCONFIGSGIXPROC)load("glXCreateGLXPixmapWithConfigSGIX");
glad_glXCreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC)load("glXCreateContextWithConfigSGIX");
glad_glXGetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC)load("glXGetVisualFromFBConfigSGIX");
glad_glXGetFBConfigFromVisualSGIX = (PFNGLXGETFBCONFIGFROMVISUALSGIXPROC)load("glXGetFBConfigFromVisualSGIX");
}
static void load_GLX_SGIX_hyperpipe(GLADloadproc load) {
if(!GLAD_GLX_SGIX_hyperpipe) return;
glad_glXQueryHyperpipeNetworkSGIX = (PFNGLXQUERYHYPERPIPENETWORKSGIXPROC)load("glXQueryHyperpipeNetworkSGIX");
glad_glXHyperpipeConfigSGIX = (PFNGLXHYPERPIPECONFIGSGIXPROC)load("glXHyperpipeConfigSGIX");
glad_glXQueryHyperpipeConfigSGIX = (PFNGLXQUERYHYPERPIPECONFIGSGIXPROC)load("glXQueryHyperpipeConfigSGIX");
glad_glXDestroyHyperpipeConfigSGIX = (PFNGLXDESTROYHYPERPIPECONFIGSGIXPROC)load("glXDestroyHyperpipeConfigSGIX");
glad_glXBindHyperpipeSGIX = (PFNGLXBINDHYPERPIPESGIXPROC)load("glXBindHyperpipeSGIX");
glad_glXQueryHyperpipeBestAttribSGIX = (PFNGLXQUERYHYPERPIPEBESTATTRIBSGIXPROC)load("glXQueryHyperpipeBestAttribSGIX");
glad_glXHyperpipeAttribSGIX = (PFNGLXHYPERPIPEATTRIBSGIXPROC)load("glXHyperpipeAttribSGIX");
glad_glXQueryHyperpipeAttribSGIX = (PFNGLXQUERYHYPERPIPEATTRIBSGIXPROC)load("glXQueryHyperpipeAttribSGIX");
}
static void load_GLX_SGIX_pbuffer(GLADloadproc load) {
if(!GLAD_GLX_SGIX_pbuffer) return;
glad_glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)load("glXCreateGLXPbufferSGIX");
glad_glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)load("glXDestroyGLXPbufferSGIX");
glad_glXQueryGLXPbufferSGIX = (PFNGLXQUERYGLXPBUFFERSGIXPROC)load("glXQueryGLXPbufferSGIX");
glad_glXSelectEventSGIX = (PFNGLXSELECTEVENTSGIXPROC)load("glXSelectEventSGIX");
glad_glXGetSelectedEventSGIX = (PFNGLXGETSELECTEDEVENTSGIXPROC)load("glXGetSelectedEventSGIX");
}
static void load_GLX_SGIX_swap_barrier(GLADloadproc load) {
if(!GLAD_GLX_SGIX_swap_barrier) return;
glad_glXBindSwapBarrierSGIX = (PFNGLXBINDSWAPBARRIERSGIXPROC)load("glXBindSwapBarrierSGIX");
glad_glXQueryMaxSwapBarriersSGIX = (PFNGLXQUERYMAXSWAPBARRIERSSGIXPROC)load("glXQueryMaxSwapBarriersSGIX");
}
static void load_GLX_SGIX_swap_group(GLADloadproc load) {
if(!GLAD_GLX_SGIX_swap_group) return;
glad_glXJoinSwapGroupSGIX = (PFNGLXJOINSWAPGROUPSGIXPROC)load("glXJoinSwapGroupSGIX");
}
static void load_GLX_SGIX_video_resize(GLADloadproc load) {
if(!GLAD_GLX_SGIX_video_resize) return;
glad_glXBindChannelToWindowSGIX = (PFNGLXBINDCHANNELTOWINDOWSGIXPROC)load("glXBindChannelToWindowSGIX");
glad_glXChannelRectSGIX = (PFNGLXCHANNELRECTSGIXPROC)load("glXChannelRectSGIX");
glad_glXQueryChannelRectSGIX = (PFNGLXQUERYCHANNELRECTSGIXPROC)load("glXQueryChannelRectSGIX");
glad_glXQueryChannelDeltasSGIX = (PFNGLXQUERYCHANNELDELTASSGIXPROC)load("glXQueryChannelDeltasSGIX");
glad_glXChannelRectSyncSGIX = (PFNGLXCHANNELRECTSYNCSGIXPROC)load("glXChannelRectSyncSGIX");
}
static void load_GLX_SGIX_video_source(GLADloadproc load) {
if(!GLAD_GLX_SGIX_video_source) return;
#ifdef _VL_H_
glad_glXCreateGLXVideoSourceSGIX = (PFNGLXCREATEGLXVIDEOSOURCESGIXPROC)load("glXCreateGLXVideoSourceSGIX");
glad_glXDestroyGLXVideoSourceSGIX = (PFNGLXDESTROYGLXVIDEOSOURCESGIXPROC)load("glXDestroyGLXVideoSourceSGIX");
#else
(void)load;
#endif
}
static void load_GLX_SGI_cushion(GLADloadproc load) {
if(!GLAD_GLX_SGI_cushion) return;
glad_glXCushionSGI = (PFNGLXCUSHIONSGIPROC)load("glXCushionSGI");
}
static void load_GLX_SGI_make_current_read(GLADloadproc load) {
if(!GLAD_GLX_SGI_make_current_read) return;
glad_glXMakeCurrentReadSGI = (PFNGLXMAKECURRENTREADSGIPROC)load("glXMakeCurrentReadSGI");
glad_glXGetCurrentReadDrawableSGI = (PFNGLXGETCURRENTREADDRAWABLESGIPROC)load("glXGetCurrentReadDrawableSGI");
}
static void load_GLX_SGI_swap_control(GLADloadproc load) {
if(!GLAD_GLX_SGI_swap_control) return;
glad_glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)load("glXSwapIntervalSGI");
}
static void load_GLX_SGI_video_sync(GLADloadproc load) {
if(!GLAD_GLX_SGI_video_sync) return;
glad_glXGetVideoSyncSGI = (PFNGLXGETVIDEOSYNCSGIPROC)load("glXGetVideoSyncSGI");
glad_glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)load("glXWaitVideoSyncSGI");
}
static void load_GLX_SUN_get_transparent_index(GLADloadproc load) {
if(!GLAD_GLX_SUN_get_transparent_index) return;
glad_glXGetTransparentIndexSUN = (PFNGLXGETTRANSPARENTINDEXSUNPROC)load("glXGetTransparentIndexSUN");
}
static int find_extensionsGLX(void) {
if (!get_exts()) return 0;
GLAD_GLX_3DFX_multisample = has_ext("GLX_3DFX_multisample");
GLAD_GLX_AMD_gpu_association = has_ext("GLX_AMD_gpu_association");
GLAD_GLX_ARB_context_flush_control = has_ext("GLX_ARB_context_flush_control");
GLAD_GLX_ARB_create_context = has_ext("GLX_ARB_create_context");
GLAD_GLX_ARB_create_context_no_error = has_ext("GLX_ARB_create_context_no_error");
GLAD_GLX_ARB_create_context_profile = has_ext("GLX_ARB_create_context_profile");
GLAD_GLX_ARB_create_context_robustness = has_ext("GLX_ARB_create_context_robustness");
GLAD_GLX_ARB_fbconfig_float = has_ext("GLX_ARB_fbconfig_float");
GLAD_GLX_ARB_framebuffer_sRGB = has_ext("GLX_ARB_framebuffer_sRGB");
GLAD_GLX_ARB_get_proc_address = has_ext("GLX_ARB_get_proc_address");
GLAD_GLX_ARB_multisample = has_ext("GLX_ARB_multisample");
GLAD_GLX_ARB_robustness_application_isolation = has_ext("GLX_ARB_robustness_application_isolation");
GLAD_GLX_ARB_robustness_share_group_isolation = has_ext("GLX_ARB_robustness_share_group_isolation");
GLAD_GLX_ARB_vertex_buffer_object = has_ext("GLX_ARB_vertex_buffer_object");
GLAD_GLX_EXT_buffer_age = has_ext("GLX_EXT_buffer_age");
GLAD_GLX_EXT_context_priority = has_ext("GLX_EXT_context_priority");
GLAD_GLX_EXT_create_context_es2_profile = has_ext("GLX_EXT_create_context_es2_profile");
GLAD_GLX_EXT_create_context_es_profile = has_ext("GLX_EXT_create_context_es_profile");
GLAD_GLX_EXT_fbconfig_packed_float = has_ext("GLX_EXT_fbconfig_packed_float");
GLAD_GLX_EXT_framebuffer_sRGB = has_ext("GLX_EXT_framebuffer_sRGB");
GLAD_GLX_EXT_get_drawable_type = has_ext("GLX_EXT_get_drawable_type");
GLAD_GLX_EXT_import_context = has_ext("GLX_EXT_import_context");
GLAD_GLX_EXT_libglvnd = has_ext("GLX_EXT_libglvnd");
GLAD_GLX_EXT_no_config_context = has_ext("GLX_EXT_no_config_context");
GLAD_GLX_EXT_stereo_tree = has_ext("GLX_EXT_stereo_tree");
GLAD_GLX_EXT_swap_control = has_ext("GLX_EXT_swap_control");
GLAD_GLX_EXT_swap_control_tear = has_ext("GLX_EXT_swap_control_tear");
GLAD_GLX_EXT_texture_from_pixmap = has_ext("GLX_EXT_texture_from_pixmap");
GLAD_GLX_EXT_visual_info = has_ext("GLX_EXT_visual_info");
GLAD_GLX_EXT_visual_rating = has_ext("GLX_EXT_visual_rating");
GLAD_GLX_INTEL_swap_event = has_ext("GLX_INTEL_swap_event");
GLAD_GLX_MESA_agp_offset = has_ext("GLX_MESA_agp_offset");
GLAD_GLX_MESA_copy_sub_buffer = has_ext("GLX_MESA_copy_sub_buffer");
GLAD_GLX_MESA_pixmap_colormap = has_ext("GLX_MESA_pixmap_colormap");
GLAD_GLX_MESA_query_renderer = has_ext("GLX_MESA_query_renderer");
GLAD_GLX_MESA_release_buffers = has_ext("GLX_MESA_release_buffers");
GLAD_GLX_MESA_set_3dfx_mode = has_ext("GLX_MESA_set_3dfx_mode");
GLAD_GLX_MESA_swap_control = has_ext("GLX_MESA_swap_control");
GLAD_GLX_NV_copy_buffer = has_ext("GLX_NV_copy_buffer");
GLAD_GLX_NV_copy_image = has_ext("GLX_NV_copy_image");
GLAD_GLX_NV_delay_before_swap = has_ext("GLX_NV_delay_before_swap");
GLAD_GLX_NV_float_buffer = has_ext("GLX_NV_float_buffer");
GLAD_GLX_NV_multigpu_context = has_ext("GLX_NV_multigpu_context");
GLAD_GLX_NV_multisample_coverage = has_ext("GLX_NV_multisample_coverage");
GLAD_GLX_NV_present_video = has_ext("GLX_NV_present_video");
GLAD_GLX_NV_robustness_video_memory_purge = has_ext("GLX_NV_robustness_video_memory_purge");
GLAD_GLX_NV_swap_group = has_ext("GLX_NV_swap_group");
GLAD_GLX_NV_video_capture = has_ext("GLX_NV_video_capture");
GLAD_GLX_NV_video_out = has_ext("GLX_NV_video_out");
GLAD_GLX_OML_swap_method = has_ext("GLX_OML_swap_method");
GLAD_GLX_OML_sync_control = has_ext("GLX_OML_sync_control");
GLAD_GLX_SGIS_blended_overlay = has_ext("GLX_SGIS_blended_overlay");
GLAD_GLX_SGIS_multisample = has_ext("GLX_SGIS_multisample");
GLAD_GLX_SGIS_shared_multisample = has_ext("GLX_SGIS_shared_multisample");
GLAD_GLX_SGIX_dmbuffer = has_ext("GLX_SGIX_dmbuffer");
GLAD_GLX_SGIX_fbconfig = has_ext("GLX_SGIX_fbconfig");
GLAD_GLX_SGIX_hyperpipe = has_ext("GLX_SGIX_hyperpipe");
GLAD_GLX_SGIX_pbuffer = has_ext("GLX_SGIX_pbuffer");
GLAD_GLX_SGIX_swap_barrier = has_ext("GLX_SGIX_swap_barrier");
GLAD_GLX_SGIX_swap_group = has_ext("GLX_SGIX_swap_group");
GLAD_GLX_SGIX_video_resize = has_ext("GLX_SGIX_video_resize");
GLAD_GLX_SGIX_video_source = has_ext("GLX_SGIX_video_source");
GLAD_GLX_SGIX_visual_select_group = has_ext("GLX_SGIX_visual_select_group");
GLAD_GLX_SGI_cushion = has_ext("GLX_SGI_cushion");
GLAD_GLX_SGI_make_current_read = has_ext("GLX_SGI_make_current_read");
GLAD_GLX_SGI_swap_control = has_ext("GLX_SGI_swap_control");
GLAD_GLX_SGI_video_sync = has_ext("GLX_SGI_video_sync");
GLAD_GLX_SUN_get_transparent_index = has_ext("GLX_SUN_get_transparent_index");
free_exts();
return 1;
}
static void find_coreGLX(Display *dpy, int screen) {
int major = 0, minor = 0;
if(dpy == 0 && GLADGLXDisplay == 0) {
dpy = XOpenDisplay(0);
screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(dpy));
} else if(dpy == 0) {
dpy = GLADGLXDisplay;
screen = GLADGLXscreen;
}
glXQueryVersion(dpy, &major, &minor);
GLADGLXDisplay = dpy;
GLADGLXscreen = screen;
GLAD_GLX_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
GLAD_GLX_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
GLAD_GLX_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
GLAD_GLX_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
GLAD_GLX_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
}
int gladLoadGLXLoader(GLADloadproc load, Display *dpy, int screen) {
glXQueryVersion = (PFNGLXQUERYVERSIONPROC)load("glXQueryVersion");
if(glXQueryVersion == NULL) return 0;
find_coreGLX(dpy, screen);
load_GLX_VERSION_1_0(load);
load_GLX_VERSION_1_1(load);
load_GLX_VERSION_1_2(load);
load_GLX_VERSION_1_3(load);
load_GLX_VERSION_1_4(load);
if (!find_extensionsGLX()) return 0;
load_GLX_AMD_gpu_association(load);
load_GLX_ARB_create_context(load);
load_GLX_ARB_get_proc_address(load);
load_GLX_EXT_import_context(load);
load_GLX_EXT_swap_control(load);
load_GLX_EXT_texture_from_pixmap(load);
load_GLX_MESA_agp_offset(load);
load_GLX_MESA_copy_sub_buffer(load);
load_GLX_MESA_pixmap_colormap(load);
load_GLX_MESA_query_renderer(load);
load_GLX_MESA_release_buffers(load);
load_GLX_MESA_set_3dfx_mode(load);
load_GLX_MESA_swap_control(load);
load_GLX_NV_copy_buffer(load);
load_GLX_NV_copy_image(load);
load_GLX_NV_delay_before_swap(load);
load_GLX_NV_present_video(load);
load_GLX_NV_swap_group(load);
load_GLX_NV_video_capture(load);
load_GLX_NV_video_out(load);
load_GLX_OML_sync_control(load);
load_GLX_SGIX_dmbuffer(load);
load_GLX_SGIX_fbconfig(load);
load_GLX_SGIX_hyperpipe(load);
load_GLX_SGIX_pbuffer(load);
load_GLX_SGIX_swap_barrier(load);
load_GLX_SGIX_swap_group(load);
load_GLX_SGIX_video_resize(load);
load_GLX_SGIX_video_source(load);
load_GLX_SGI_cushion(load);
load_GLX_SGI_make_current_read(load);
load_GLX_SGI_swap_control(load);
load_GLX_SGI_video_sync(load);
load_GLX_SUN_get_transparent_index(load);
return 1;
}
+756
View File
@@ -0,0 +1,756 @@
/*
WGL loader generated by glad 0.1.36 on Thu Sep 15 11:18:46 2022.
Language/Generator: C/C++
Specification: wgl
APIs: wgl=1.0
Profile: -
Extensions:
WGL_3DFX_multisample,
WGL_3DL_stereo_control,
WGL_AMD_gpu_association,
WGL_ARB_buffer_region,
WGL_ARB_context_flush_control,
WGL_ARB_create_context,
WGL_ARB_create_context_no_error,
WGL_ARB_create_context_profile,
WGL_ARB_create_context_robustness,
WGL_ARB_extensions_string,
WGL_ARB_framebuffer_sRGB,
WGL_ARB_make_current_read,
WGL_ARB_multisample,
WGL_ARB_pbuffer,
WGL_ARB_pixel_format,
WGL_ARB_pixel_format_float,
WGL_ARB_render_texture,
WGL_ARB_robustness_application_isolation,
WGL_ARB_robustness_share_group_isolation,
WGL_ATI_pixel_format_float,
WGL_ATI_render_texture_rectangle,
WGL_EXT_colorspace,
WGL_EXT_create_context_es2_profile,
WGL_EXT_create_context_es_profile,
WGL_EXT_depth_float,
WGL_EXT_display_color_table,
WGL_EXT_extensions_string,
WGL_EXT_framebuffer_sRGB,
WGL_EXT_make_current_read,
WGL_EXT_multisample,
WGL_EXT_pbuffer,
WGL_EXT_pixel_format,
WGL_EXT_pixel_format_packed_float,
WGL_EXT_swap_control,
WGL_EXT_swap_control_tear,
WGL_I3D_digital_video_control,
WGL_I3D_gamma,
WGL_I3D_genlock,
WGL_I3D_image_buffer,
WGL_I3D_swap_frame_lock,
WGL_I3D_swap_frame_usage,
WGL_NV_DX_interop,
WGL_NV_DX_interop2,
WGL_NV_copy_image,
WGL_NV_delay_before_swap,
WGL_NV_float_buffer,
WGL_NV_gpu_affinity,
WGL_NV_multigpu_context,
WGL_NV_multisample_coverage,
WGL_NV_present_video,
WGL_NV_render_depth_texture,
WGL_NV_render_texture_rectangle,
WGL_NV_swap_group,
WGL_NV_vertex_array_range,
WGL_NV_video_capture,
WGL_NV_video_output,
WGL_OML_sync_control
Loader: True
Local files: True
Omit khrplatform: False
Reproducible: False
Commandline:
--api="wgl=1.0" --generator="c" --spec="wgl" --local-files --extensions="WGL_3DFX_multisample,WGL_3DL_stereo_control,WGL_AMD_gpu_association,WGL_ARB_buffer_region,WGL_ARB_context_flush_control,WGL_ARB_create_context,WGL_ARB_create_context_no_error,WGL_ARB_create_context_profile,WGL_ARB_create_context_robustness,WGL_ARB_extensions_string,WGL_ARB_framebuffer_sRGB,WGL_ARB_make_current_read,WGL_ARB_multisample,WGL_ARB_pbuffer,WGL_ARB_pixel_format,WGL_ARB_pixel_format_float,WGL_ARB_render_texture,WGL_ARB_robustness_application_isolation,WGL_ARB_robustness_share_group_isolation,WGL_ATI_pixel_format_float,WGL_ATI_render_texture_rectangle,WGL_EXT_colorspace,WGL_EXT_create_context_es2_profile,WGL_EXT_create_context_es_profile,WGL_EXT_depth_float,WGL_EXT_display_color_table,WGL_EXT_extensions_string,WGL_EXT_framebuffer_sRGB,WGL_EXT_make_current_read,WGL_EXT_multisample,WGL_EXT_pbuffer,WGL_EXT_pixel_format,WGL_EXT_pixel_format_packed_float,WGL_EXT_swap_control,WGL_EXT_swap_control_tear,WGL_I3D_digital_video_control,WGL_I3D_gamma,WGL_I3D_genlock,WGL_I3D_image_buffer,WGL_I3D_swap_frame_lock,WGL_I3D_swap_frame_usage,WGL_NV_DX_interop,WGL_NV_DX_interop2,WGL_NV_copy_image,WGL_NV_delay_before_swap,WGL_NV_float_buffer,WGL_NV_gpu_affinity,WGL_NV_multigpu_context,WGL_NV_multisample_coverage,WGL_NV_present_video,WGL_NV_render_depth_texture,WGL_NV_render_texture_rectangle,WGL_NV_swap_group,WGL_NV_vertex_array_range,WGL_NV_video_capture,WGL_NV_video_output,WGL_OML_sync_control"
Online:
Too many extensions
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glad/glad_wgl.h>
static void* get_proc(const char *namez);
#if defined(_WIN32) || defined(__CYGWIN__)
#ifndef _WINDOWS_
#undef APIENTRY
#endif
#include <windows.h>
static HMODULE libGL;
typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*);
static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
#ifdef _MSC_VER
#ifdef __has_include
#if __has_include(<winapifamily.h>)
#define HAVE_WINAPIFAMILY 1
#endif
#elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
#define HAVE_WINAPIFAMILY 1
#endif
#endif
#ifdef HAVE_WINAPIFAMILY
#include <winapifamily.h>
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
#define IS_UWP 1
#endif
#endif
static
int open_wgl(void) {
#ifndef IS_UWP
libGL = LoadLibraryW(L"opengl32.dll");
if(libGL != NULL) {
void (* tmp)(void);
tmp = (void(*)(void)) GetProcAddress(libGL, "wglGetProcAddress");
gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE) tmp;
return gladGetProcAddressPtr != NULL;
}
#endif
return 0;
}
static
void close_wgl(void) {
if(libGL != NULL) {
FreeLibrary((HMODULE) libGL);
libGL = NULL;
}
}
#else
#include <dlfcn.h>
static void* libGL;
#if !defined(__APPLE__) && !defined(__HAIKU__)
typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*);
static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
#endif
static
int open_wgl(void) {
#ifdef __APPLE__
static const char *NAMES[] = {
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
};
#else
static const char *NAMES[] = {"libGL.so.1", "libGL.so"};
#endif
unsigned int index = 0;
for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) {
libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL);
if(libGL != NULL) {
#if defined(__APPLE__) || defined(__HAIKU__)
return 1;
#else
gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL,
"glXGetProcAddressARB");
return gladGetProcAddressPtr != NULL;
#endif
}
}
return 0;
}
static
void close_wgl(void) {
if(libGL != NULL) {
dlclose(libGL);
libGL = NULL;
}
}
#endif
static
void* get_proc(const char *namez) {
void* result = NULL;
if(libGL == NULL) return NULL;
#if !defined(__APPLE__) && !defined(__HAIKU__)
if(gladGetProcAddressPtr != NULL) {
result = gladGetProcAddressPtr(namez);
}
#endif
if(result == NULL) {
#if defined(_WIN32) || defined(__CYGWIN__)
result = (void*)GetProcAddress((HMODULE) libGL, namez);
#else
result = dlsym(libGL, namez);
#endif
}
return result;
}
int gladLoadWGL(HDC hdc) {
int status = 0;
if(open_wgl()) {
status = gladLoadWGLLoader((GLADloadproc)get_proc, hdc);
}
return status;
}
void gladUnloadGLX(void) {
close_wgl();
}
static HDC GLADWGLhdc = (HDC)INVALID_HANDLE_VALUE;
static int get_exts(void) {
return 1;
}
static void free_exts(void) {
return;
}
static int has_ext(const char *ext) {
const char *terminator;
const char *loc;
const char *extensions;
if(wglGetExtensionsStringEXT == NULL && wglGetExtensionsStringARB == NULL)
return 0;
if(wglGetExtensionsStringARB == NULL || GLADWGLhdc == INVALID_HANDLE_VALUE)
extensions = wglGetExtensionsStringEXT();
else
extensions = wglGetExtensionsStringARB(GLADWGLhdc);
if(extensions == NULL || ext == NULL)
return 0;
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL)
break;
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\0'))
{
return 1;
}
extensions = terminator;
}
return 0;
}
int GLAD_WGL_VERSION_1_0 = 0;
int GLAD_WGL_3DFX_multisample = 0;
int GLAD_WGL_3DL_stereo_control = 0;
int GLAD_WGL_AMD_gpu_association = 0;
int GLAD_WGL_ARB_buffer_region = 0;
int GLAD_WGL_ARB_context_flush_control = 0;
int GLAD_WGL_ARB_create_context = 0;
int GLAD_WGL_ARB_create_context_no_error = 0;
int GLAD_WGL_ARB_create_context_profile = 0;
int GLAD_WGL_ARB_create_context_robustness = 0;
int GLAD_WGL_ARB_extensions_string = 0;
int GLAD_WGL_ARB_framebuffer_sRGB = 0;
int GLAD_WGL_ARB_make_current_read = 0;
int GLAD_WGL_ARB_multisample = 0;
int GLAD_WGL_ARB_pbuffer = 0;
int GLAD_WGL_ARB_pixel_format = 0;
int GLAD_WGL_ARB_pixel_format_float = 0;
int GLAD_WGL_ARB_render_texture = 0;
int GLAD_WGL_ARB_robustness_application_isolation = 0;
int GLAD_WGL_ARB_robustness_share_group_isolation = 0;
int GLAD_WGL_ATI_pixel_format_float = 0;
int GLAD_WGL_ATI_render_texture_rectangle = 0;
int GLAD_WGL_EXT_colorspace = 0;
int GLAD_WGL_EXT_create_context_es2_profile = 0;
int GLAD_WGL_EXT_create_context_es_profile = 0;
int GLAD_WGL_EXT_depth_float = 0;
int GLAD_WGL_EXT_display_color_table = 0;
int GLAD_WGL_EXT_extensions_string = 0;
int GLAD_WGL_EXT_framebuffer_sRGB = 0;
int GLAD_WGL_EXT_make_current_read = 0;
int GLAD_WGL_EXT_multisample = 0;
int GLAD_WGL_EXT_pbuffer = 0;
int GLAD_WGL_EXT_pixel_format = 0;
int GLAD_WGL_EXT_pixel_format_packed_float = 0;
int GLAD_WGL_EXT_swap_control = 0;
int GLAD_WGL_EXT_swap_control_tear = 0;
int GLAD_WGL_I3D_digital_video_control = 0;
int GLAD_WGL_I3D_gamma = 0;
int GLAD_WGL_I3D_genlock = 0;
int GLAD_WGL_I3D_image_buffer = 0;
int GLAD_WGL_I3D_swap_frame_lock = 0;
int GLAD_WGL_I3D_swap_frame_usage = 0;
int GLAD_WGL_NV_DX_interop = 0;
int GLAD_WGL_NV_DX_interop2 = 0;
int GLAD_WGL_NV_copy_image = 0;
int GLAD_WGL_NV_delay_before_swap = 0;
int GLAD_WGL_NV_float_buffer = 0;
int GLAD_WGL_NV_gpu_affinity = 0;
int GLAD_WGL_NV_multigpu_context = 0;
int GLAD_WGL_NV_multisample_coverage = 0;
int GLAD_WGL_NV_present_video = 0;
int GLAD_WGL_NV_render_depth_texture = 0;
int GLAD_WGL_NV_render_texture_rectangle = 0;
int GLAD_WGL_NV_swap_group = 0;
int GLAD_WGL_NV_vertex_array_range = 0;
int GLAD_WGL_NV_video_capture = 0;
int GLAD_WGL_NV_video_output = 0;
int GLAD_WGL_OML_sync_control = 0;
PFNWGLSETSTEREOEMITTERSTATE3DLPROC glad_wglSetStereoEmitterState3DL = NULL;
PFNWGLGETGPUIDSAMDPROC glad_wglGetGPUIDsAMD = NULL;
PFNWGLGETGPUINFOAMDPROC glad_wglGetGPUInfoAMD = NULL;
PFNWGLGETCONTEXTGPUIDAMDPROC glad_wglGetContextGPUIDAMD = NULL;
PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC glad_wglCreateAssociatedContextAMD = NULL;
PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC glad_wglCreateAssociatedContextAttribsAMD = NULL;
PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC glad_wglDeleteAssociatedContextAMD = NULL;
PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC glad_wglMakeAssociatedContextCurrentAMD = NULL;
PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC glad_wglGetCurrentAssociatedContextAMD = NULL;
PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC glad_wglBlitContextFramebufferAMD = NULL;
PFNWGLCREATEBUFFERREGIONARBPROC glad_wglCreateBufferRegionARB = NULL;
PFNWGLDELETEBUFFERREGIONARBPROC glad_wglDeleteBufferRegionARB = NULL;
PFNWGLSAVEBUFFERREGIONARBPROC glad_wglSaveBufferRegionARB = NULL;
PFNWGLRESTOREBUFFERREGIONARBPROC glad_wglRestoreBufferRegionARB = NULL;
PFNWGLCREATECONTEXTATTRIBSARBPROC glad_wglCreateContextAttribsARB = NULL;
PFNWGLGETEXTENSIONSSTRINGARBPROC glad_wglGetExtensionsStringARB = NULL;
PFNWGLMAKECONTEXTCURRENTARBPROC glad_wglMakeContextCurrentARB = NULL;
PFNWGLGETCURRENTREADDCARBPROC glad_wglGetCurrentReadDCARB = NULL;
PFNWGLCREATEPBUFFERARBPROC glad_wglCreatePbufferARB = NULL;
PFNWGLGETPBUFFERDCARBPROC glad_wglGetPbufferDCARB = NULL;
PFNWGLRELEASEPBUFFERDCARBPROC glad_wglReleasePbufferDCARB = NULL;
PFNWGLDESTROYPBUFFERARBPROC glad_wglDestroyPbufferARB = NULL;
PFNWGLQUERYPBUFFERARBPROC glad_wglQueryPbufferARB = NULL;
PFNWGLGETPIXELFORMATATTRIBIVARBPROC glad_wglGetPixelFormatAttribivARB = NULL;
PFNWGLGETPIXELFORMATATTRIBFVARBPROC glad_wglGetPixelFormatAttribfvARB = NULL;
PFNWGLCHOOSEPIXELFORMATARBPROC glad_wglChoosePixelFormatARB = NULL;
PFNWGLBINDTEXIMAGEARBPROC glad_wglBindTexImageARB = NULL;
PFNWGLRELEASETEXIMAGEARBPROC glad_wglReleaseTexImageARB = NULL;
PFNWGLSETPBUFFERATTRIBARBPROC glad_wglSetPbufferAttribARB = NULL;
PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC glad_wglCreateDisplayColorTableEXT = NULL;
PFNWGLLOADDISPLAYCOLORTABLEEXTPROC glad_wglLoadDisplayColorTableEXT = NULL;
PFNWGLBINDDISPLAYCOLORTABLEEXTPROC glad_wglBindDisplayColorTableEXT = NULL;
PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC glad_wglDestroyDisplayColorTableEXT = NULL;
PFNWGLGETEXTENSIONSSTRINGEXTPROC glad_wglGetExtensionsStringEXT = NULL;
PFNWGLMAKECONTEXTCURRENTEXTPROC glad_wglMakeContextCurrentEXT = NULL;
PFNWGLGETCURRENTREADDCEXTPROC glad_wglGetCurrentReadDCEXT = NULL;
PFNWGLCREATEPBUFFEREXTPROC glad_wglCreatePbufferEXT = NULL;
PFNWGLGETPBUFFERDCEXTPROC glad_wglGetPbufferDCEXT = NULL;
PFNWGLRELEASEPBUFFERDCEXTPROC glad_wglReleasePbufferDCEXT = NULL;
PFNWGLDESTROYPBUFFEREXTPROC glad_wglDestroyPbufferEXT = NULL;
PFNWGLQUERYPBUFFEREXTPROC glad_wglQueryPbufferEXT = NULL;
PFNWGLGETPIXELFORMATATTRIBIVEXTPROC glad_wglGetPixelFormatAttribivEXT = NULL;
PFNWGLGETPIXELFORMATATTRIBFVEXTPROC glad_wglGetPixelFormatAttribfvEXT = NULL;
PFNWGLCHOOSEPIXELFORMATEXTPROC glad_wglChoosePixelFormatEXT = NULL;
PFNWGLSWAPINTERVALEXTPROC glad_wglSwapIntervalEXT = NULL;
PFNWGLGETSWAPINTERVALEXTPROC glad_wglGetSwapIntervalEXT = NULL;
PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC glad_wglGetDigitalVideoParametersI3D = NULL;
PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC glad_wglSetDigitalVideoParametersI3D = NULL;
PFNWGLGETGAMMATABLEPARAMETERSI3DPROC glad_wglGetGammaTableParametersI3D = NULL;
PFNWGLSETGAMMATABLEPARAMETERSI3DPROC glad_wglSetGammaTableParametersI3D = NULL;
PFNWGLGETGAMMATABLEI3DPROC glad_wglGetGammaTableI3D = NULL;
PFNWGLSETGAMMATABLEI3DPROC glad_wglSetGammaTableI3D = NULL;
PFNWGLENABLEGENLOCKI3DPROC glad_wglEnableGenlockI3D = NULL;
PFNWGLDISABLEGENLOCKI3DPROC glad_wglDisableGenlockI3D = NULL;
PFNWGLISENABLEDGENLOCKI3DPROC glad_wglIsEnabledGenlockI3D = NULL;
PFNWGLGENLOCKSOURCEI3DPROC glad_wglGenlockSourceI3D = NULL;
PFNWGLGETGENLOCKSOURCEI3DPROC glad_wglGetGenlockSourceI3D = NULL;
PFNWGLGENLOCKSOURCEEDGEI3DPROC glad_wglGenlockSourceEdgeI3D = NULL;
PFNWGLGETGENLOCKSOURCEEDGEI3DPROC glad_wglGetGenlockSourceEdgeI3D = NULL;
PFNWGLGENLOCKSAMPLERATEI3DPROC glad_wglGenlockSampleRateI3D = NULL;
PFNWGLGETGENLOCKSAMPLERATEI3DPROC glad_wglGetGenlockSampleRateI3D = NULL;
PFNWGLGENLOCKSOURCEDELAYI3DPROC glad_wglGenlockSourceDelayI3D = NULL;
PFNWGLGETGENLOCKSOURCEDELAYI3DPROC glad_wglGetGenlockSourceDelayI3D = NULL;
PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC glad_wglQueryGenlockMaxSourceDelayI3D = NULL;
PFNWGLCREATEIMAGEBUFFERI3DPROC glad_wglCreateImageBufferI3D = NULL;
PFNWGLDESTROYIMAGEBUFFERI3DPROC glad_wglDestroyImageBufferI3D = NULL;
PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC glad_wglAssociateImageBufferEventsI3D = NULL;
PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC glad_wglReleaseImageBufferEventsI3D = NULL;
PFNWGLENABLEFRAMELOCKI3DPROC glad_wglEnableFrameLockI3D = NULL;
PFNWGLDISABLEFRAMELOCKI3DPROC glad_wglDisableFrameLockI3D = NULL;
PFNWGLISENABLEDFRAMELOCKI3DPROC glad_wglIsEnabledFrameLockI3D = NULL;
PFNWGLQUERYFRAMELOCKMASTERI3DPROC glad_wglQueryFrameLockMasterI3D = NULL;
PFNWGLGETFRAMEUSAGEI3DPROC glad_wglGetFrameUsageI3D = NULL;
PFNWGLBEGINFRAMETRACKINGI3DPROC glad_wglBeginFrameTrackingI3D = NULL;
PFNWGLENDFRAMETRACKINGI3DPROC glad_wglEndFrameTrackingI3D = NULL;
PFNWGLQUERYFRAMETRACKINGI3DPROC glad_wglQueryFrameTrackingI3D = NULL;
PFNWGLDXSETRESOURCESHAREHANDLENVPROC glad_wglDXSetResourceShareHandleNV = NULL;
PFNWGLDXOPENDEVICENVPROC glad_wglDXOpenDeviceNV = NULL;
PFNWGLDXCLOSEDEVICENVPROC glad_wglDXCloseDeviceNV = NULL;
PFNWGLDXREGISTEROBJECTNVPROC glad_wglDXRegisterObjectNV = NULL;
PFNWGLDXUNREGISTEROBJECTNVPROC glad_wglDXUnregisterObjectNV = NULL;
PFNWGLDXOBJECTACCESSNVPROC glad_wglDXObjectAccessNV = NULL;
PFNWGLDXLOCKOBJECTSNVPROC glad_wglDXLockObjectsNV = NULL;
PFNWGLDXUNLOCKOBJECTSNVPROC glad_wglDXUnlockObjectsNV = NULL;
PFNWGLCOPYIMAGESUBDATANVPROC glad_wglCopyImageSubDataNV = NULL;
PFNWGLDELAYBEFORESWAPNVPROC glad_wglDelayBeforeSwapNV = NULL;
PFNWGLENUMGPUSNVPROC glad_wglEnumGpusNV = NULL;
PFNWGLENUMGPUDEVICESNVPROC glad_wglEnumGpuDevicesNV = NULL;
PFNWGLCREATEAFFINITYDCNVPROC glad_wglCreateAffinityDCNV = NULL;
PFNWGLENUMGPUSFROMAFFINITYDCNVPROC glad_wglEnumGpusFromAffinityDCNV = NULL;
PFNWGLDELETEDCNVPROC glad_wglDeleteDCNV = NULL;
PFNWGLENUMERATEVIDEODEVICESNVPROC glad_wglEnumerateVideoDevicesNV = NULL;
PFNWGLBINDVIDEODEVICENVPROC glad_wglBindVideoDeviceNV = NULL;
PFNWGLQUERYCURRENTCONTEXTNVPROC glad_wglQueryCurrentContextNV = NULL;
PFNWGLJOINSWAPGROUPNVPROC glad_wglJoinSwapGroupNV = NULL;
PFNWGLBINDSWAPBARRIERNVPROC glad_wglBindSwapBarrierNV = NULL;
PFNWGLQUERYSWAPGROUPNVPROC glad_wglQuerySwapGroupNV = NULL;
PFNWGLQUERYMAXSWAPGROUPSNVPROC glad_wglQueryMaxSwapGroupsNV = NULL;
PFNWGLQUERYFRAMECOUNTNVPROC glad_wglQueryFrameCountNV = NULL;
PFNWGLRESETFRAMECOUNTNVPROC glad_wglResetFrameCountNV = NULL;
PFNWGLALLOCATEMEMORYNVPROC glad_wglAllocateMemoryNV = NULL;
PFNWGLFREEMEMORYNVPROC glad_wglFreeMemoryNV = NULL;
PFNWGLBINDVIDEOCAPTUREDEVICENVPROC glad_wglBindVideoCaptureDeviceNV = NULL;
PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC glad_wglEnumerateVideoCaptureDevicesNV = NULL;
PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC glad_wglLockVideoCaptureDeviceNV = NULL;
PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC glad_wglQueryVideoCaptureDeviceNV = NULL;
PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC glad_wglReleaseVideoCaptureDeviceNV = NULL;
PFNWGLGETVIDEODEVICENVPROC glad_wglGetVideoDeviceNV = NULL;
PFNWGLRELEASEVIDEODEVICENVPROC glad_wglReleaseVideoDeviceNV = NULL;
PFNWGLBINDVIDEOIMAGENVPROC glad_wglBindVideoImageNV = NULL;
PFNWGLRELEASEVIDEOIMAGENVPROC glad_wglReleaseVideoImageNV = NULL;
PFNWGLSENDPBUFFERTOVIDEONVPROC glad_wglSendPbufferToVideoNV = NULL;
PFNWGLGETVIDEOINFONVPROC glad_wglGetVideoInfoNV = NULL;
PFNWGLGETSYNCVALUESOMLPROC glad_wglGetSyncValuesOML = NULL;
PFNWGLGETMSCRATEOMLPROC glad_wglGetMscRateOML = NULL;
PFNWGLSWAPBUFFERSMSCOMLPROC glad_wglSwapBuffersMscOML = NULL;
PFNWGLSWAPLAYERBUFFERSMSCOMLPROC glad_wglSwapLayerBuffersMscOML = NULL;
PFNWGLWAITFORMSCOMLPROC glad_wglWaitForMscOML = NULL;
PFNWGLWAITFORSBCOMLPROC glad_wglWaitForSbcOML = NULL;
static void load_WGL_3DL_stereo_control(GLADloadproc load) {
if(!GLAD_WGL_3DL_stereo_control) return;
glad_wglSetStereoEmitterState3DL = (PFNWGLSETSTEREOEMITTERSTATE3DLPROC)load("wglSetStereoEmitterState3DL");
}
static void load_WGL_AMD_gpu_association(GLADloadproc load) {
if(!GLAD_WGL_AMD_gpu_association) return;
glad_wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)load("wglGetGPUIDsAMD");
glad_wglGetGPUInfoAMD = (PFNWGLGETGPUINFOAMDPROC)load("wglGetGPUInfoAMD");
glad_wglGetContextGPUIDAMD = (PFNWGLGETCONTEXTGPUIDAMDPROC)load("wglGetContextGPUIDAMD");
glad_wglCreateAssociatedContextAMD = (PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC)load("wglCreateAssociatedContextAMD");
glad_wglCreateAssociatedContextAttribsAMD = (PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC)load("wglCreateAssociatedContextAttribsAMD");
glad_wglDeleteAssociatedContextAMD = (PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC)load("wglDeleteAssociatedContextAMD");
glad_wglMakeAssociatedContextCurrentAMD = (PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC)load("wglMakeAssociatedContextCurrentAMD");
glad_wglGetCurrentAssociatedContextAMD = (PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC)load("wglGetCurrentAssociatedContextAMD");
glad_wglBlitContextFramebufferAMD = (PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC)load("wglBlitContextFramebufferAMD");
}
static void load_WGL_ARB_buffer_region(GLADloadproc load) {
if(!GLAD_WGL_ARB_buffer_region) return;
glad_wglCreateBufferRegionARB = (PFNWGLCREATEBUFFERREGIONARBPROC)load("wglCreateBufferRegionARB");
glad_wglDeleteBufferRegionARB = (PFNWGLDELETEBUFFERREGIONARBPROC)load("wglDeleteBufferRegionARB");
glad_wglSaveBufferRegionARB = (PFNWGLSAVEBUFFERREGIONARBPROC)load("wglSaveBufferRegionARB");
glad_wglRestoreBufferRegionARB = (PFNWGLRESTOREBUFFERREGIONARBPROC)load("wglRestoreBufferRegionARB");
}
static void load_WGL_ARB_create_context(GLADloadproc load) {
if(!GLAD_WGL_ARB_create_context) return;
glad_wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)load("wglCreateContextAttribsARB");
}
static void load_WGL_ARB_extensions_string(GLADloadproc load) {
if(!GLAD_WGL_ARB_extensions_string) return;
glad_wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)load("wglGetExtensionsStringARB");
}
static void load_WGL_ARB_make_current_read(GLADloadproc load) {
if(!GLAD_WGL_ARB_make_current_read) return;
glad_wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC)load("wglMakeContextCurrentARB");
glad_wglGetCurrentReadDCARB = (PFNWGLGETCURRENTREADDCARBPROC)load("wglGetCurrentReadDCARB");
}
static void load_WGL_ARB_pbuffer(GLADloadproc load) {
if(!GLAD_WGL_ARB_pbuffer) return;
glad_wglCreatePbufferARB = (PFNWGLCREATEPBUFFERARBPROC)load("wglCreatePbufferARB");
glad_wglGetPbufferDCARB = (PFNWGLGETPBUFFERDCARBPROC)load("wglGetPbufferDCARB");
glad_wglReleasePbufferDCARB = (PFNWGLRELEASEPBUFFERDCARBPROC)load("wglReleasePbufferDCARB");
glad_wglDestroyPbufferARB = (PFNWGLDESTROYPBUFFERARBPROC)load("wglDestroyPbufferARB");
glad_wglQueryPbufferARB = (PFNWGLQUERYPBUFFERARBPROC)load("wglQueryPbufferARB");
}
static void load_WGL_ARB_pixel_format(GLADloadproc load) {
if(!GLAD_WGL_ARB_pixel_format) return;
glad_wglGetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)load("wglGetPixelFormatAttribivARB");
glad_wglGetPixelFormatAttribfvARB = (PFNWGLGETPIXELFORMATATTRIBFVARBPROC)load("wglGetPixelFormatAttribfvARB");
glad_wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)load("wglChoosePixelFormatARB");
}
static void load_WGL_ARB_render_texture(GLADloadproc load) {
if(!GLAD_WGL_ARB_render_texture) return;
glad_wglBindTexImageARB = (PFNWGLBINDTEXIMAGEARBPROC)load("wglBindTexImageARB");
glad_wglReleaseTexImageARB = (PFNWGLRELEASETEXIMAGEARBPROC)load("wglReleaseTexImageARB");
glad_wglSetPbufferAttribARB = (PFNWGLSETPBUFFERATTRIBARBPROC)load("wglSetPbufferAttribARB");
}
static void load_WGL_EXT_display_color_table(GLADloadproc load) {
if(!GLAD_WGL_EXT_display_color_table) return;
glad_wglCreateDisplayColorTableEXT = (PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC)load("wglCreateDisplayColorTableEXT");
glad_wglLoadDisplayColorTableEXT = (PFNWGLLOADDISPLAYCOLORTABLEEXTPROC)load("wglLoadDisplayColorTableEXT");
glad_wglBindDisplayColorTableEXT = (PFNWGLBINDDISPLAYCOLORTABLEEXTPROC)load("wglBindDisplayColorTableEXT");
glad_wglDestroyDisplayColorTableEXT = (PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC)load("wglDestroyDisplayColorTableEXT");
}
static void load_WGL_EXT_extensions_string(GLADloadproc load) {
if(!GLAD_WGL_EXT_extensions_string) return;
glad_wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)load("wglGetExtensionsStringEXT");
}
static void load_WGL_EXT_make_current_read(GLADloadproc load) {
if(!GLAD_WGL_EXT_make_current_read) return;
glad_wglMakeContextCurrentEXT = (PFNWGLMAKECONTEXTCURRENTEXTPROC)load("wglMakeContextCurrentEXT");
glad_wglGetCurrentReadDCEXT = (PFNWGLGETCURRENTREADDCEXTPROC)load("wglGetCurrentReadDCEXT");
}
static void load_WGL_EXT_pbuffer(GLADloadproc load) {
if(!GLAD_WGL_EXT_pbuffer) return;
glad_wglCreatePbufferEXT = (PFNWGLCREATEPBUFFEREXTPROC)load("wglCreatePbufferEXT");
glad_wglGetPbufferDCEXT = (PFNWGLGETPBUFFERDCEXTPROC)load("wglGetPbufferDCEXT");
glad_wglReleasePbufferDCEXT = (PFNWGLRELEASEPBUFFERDCEXTPROC)load("wglReleasePbufferDCEXT");
glad_wglDestroyPbufferEXT = (PFNWGLDESTROYPBUFFEREXTPROC)load("wglDestroyPbufferEXT");
glad_wglQueryPbufferEXT = (PFNWGLQUERYPBUFFEREXTPROC)load("wglQueryPbufferEXT");
}
static void load_WGL_EXT_pixel_format(GLADloadproc load) {
if(!GLAD_WGL_EXT_pixel_format) return;
glad_wglGetPixelFormatAttribivEXT = (PFNWGLGETPIXELFORMATATTRIBIVEXTPROC)load("wglGetPixelFormatAttribivEXT");
glad_wglGetPixelFormatAttribfvEXT = (PFNWGLGETPIXELFORMATATTRIBFVEXTPROC)load("wglGetPixelFormatAttribfvEXT");
glad_wglChoosePixelFormatEXT = (PFNWGLCHOOSEPIXELFORMATEXTPROC)load("wglChoosePixelFormatEXT");
}
static void load_WGL_EXT_swap_control(GLADloadproc load) {
if(!GLAD_WGL_EXT_swap_control) return;
glad_wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)load("wglSwapIntervalEXT");
glad_wglGetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC)load("wglGetSwapIntervalEXT");
}
static void load_WGL_I3D_digital_video_control(GLADloadproc load) {
if(!GLAD_WGL_I3D_digital_video_control) return;
glad_wglGetDigitalVideoParametersI3D = (PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC)load("wglGetDigitalVideoParametersI3D");
glad_wglSetDigitalVideoParametersI3D = (PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC)load("wglSetDigitalVideoParametersI3D");
}
static void load_WGL_I3D_gamma(GLADloadproc load) {
if(!GLAD_WGL_I3D_gamma) return;
glad_wglGetGammaTableParametersI3D = (PFNWGLGETGAMMATABLEPARAMETERSI3DPROC)load("wglGetGammaTableParametersI3D");
glad_wglSetGammaTableParametersI3D = (PFNWGLSETGAMMATABLEPARAMETERSI3DPROC)load("wglSetGammaTableParametersI3D");
glad_wglGetGammaTableI3D = (PFNWGLGETGAMMATABLEI3DPROC)load("wglGetGammaTableI3D");
glad_wglSetGammaTableI3D = (PFNWGLSETGAMMATABLEI3DPROC)load("wglSetGammaTableI3D");
}
static void load_WGL_I3D_genlock(GLADloadproc load) {
if(!GLAD_WGL_I3D_genlock) return;
glad_wglEnableGenlockI3D = (PFNWGLENABLEGENLOCKI3DPROC)load("wglEnableGenlockI3D");
glad_wglDisableGenlockI3D = (PFNWGLDISABLEGENLOCKI3DPROC)load("wglDisableGenlockI3D");
glad_wglIsEnabledGenlockI3D = (PFNWGLISENABLEDGENLOCKI3DPROC)load("wglIsEnabledGenlockI3D");
glad_wglGenlockSourceI3D = (PFNWGLGENLOCKSOURCEI3DPROC)load("wglGenlockSourceI3D");
glad_wglGetGenlockSourceI3D = (PFNWGLGETGENLOCKSOURCEI3DPROC)load("wglGetGenlockSourceI3D");
glad_wglGenlockSourceEdgeI3D = (PFNWGLGENLOCKSOURCEEDGEI3DPROC)load("wglGenlockSourceEdgeI3D");
glad_wglGetGenlockSourceEdgeI3D = (PFNWGLGETGENLOCKSOURCEEDGEI3DPROC)load("wglGetGenlockSourceEdgeI3D");
glad_wglGenlockSampleRateI3D = (PFNWGLGENLOCKSAMPLERATEI3DPROC)load("wglGenlockSampleRateI3D");
glad_wglGetGenlockSampleRateI3D = (PFNWGLGETGENLOCKSAMPLERATEI3DPROC)load("wglGetGenlockSampleRateI3D");
glad_wglGenlockSourceDelayI3D = (PFNWGLGENLOCKSOURCEDELAYI3DPROC)load("wglGenlockSourceDelayI3D");
glad_wglGetGenlockSourceDelayI3D = (PFNWGLGETGENLOCKSOURCEDELAYI3DPROC)load("wglGetGenlockSourceDelayI3D");
glad_wglQueryGenlockMaxSourceDelayI3D = (PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC)load("wglQueryGenlockMaxSourceDelayI3D");
}
static void load_WGL_I3D_image_buffer(GLADloadproc load) {
if(!GLAD_WGL_I3D_image_buffer) return;
glad_wglCreateImageBufferI3D = (PFNWGLCREATEIMAGEBUFFERI3DPROC)load("wglCreateImageBufferI3D");
glad_wglDestroyImageBufferI3D = (PFNWGLDESTROYIMAGEBUFFERI3DPROC)load("wglDestroyImageBufferI3D");
glad_wglAssociateImageBufferEventsI3D = (PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC)load("wglAssociateImageBufferEventsI3D");
glad_wglReleaseImageBufferEventsI3D = (PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC)load("wglReleaseImageBufferEventsI3D");
}
static void load_WGL_I3D_swap_frame_lock(GLADloadproc load) {
if(!GLAD_WGL_I3D_swap_frame_lock) return;
glad_wglEnableFrameLockI3D = (PFNWGLENABLEFRAMELOCKI3DPROC)load("wglEnableFrameLockI3D");
glad_wglDisableFrameLockI3D = (PFNWGLDISABLEFRAMELOCKI3DPROC)load("wglDisableFrameLockI3D");
glad_wglIsEnabledFrameLockI3D = (PFNWGLISENABLEDFRAMELOCKI3DPROC)load("wglIsEnabledFrameLockI3D");
glad_wglQueryFrameLockMasterI3D = (PFNWGLQUERYFRAMELOCKMASTERI3DPROC)load("wglQueryFrameLockMasterI3D");
}
static void load_WGL_I3D_swap_frame_usage(GLADloadproc load) {
if(!GLAD_WGL_I3D_swap_frame_usage) return;
glad_wglGetFrameUsageI3D = (PFNWGLGETFRAMEUSAGEI3DPROC)load("wglGetFrameUsageI3D");
glad_wglBeginFrameTrackingI3D = (PFNWGLBEGINFRAMETRACKINGI3DPROC)load("wglBeginFrameTrackingI3D");
glad_wglEndFrameTrackingI3D = (PFNWGLENDFRAMETRACKINGI3DPROC)load("wglEndFrameTrackingI3D");
glad_wglQueryFrameTrackingI3D = (PFNWGLQUERYFRAMETRACKINGI3DPROC)load("wglQueryFrameTrackingI3D");
}
static void load_WGL_NV_DX_interop(GLADloadproc load) {
if(!GLAD_WGL_NV_DX_interop) return;
glad_wglDXSetResourceShareHandleNV = (PFNWGLDXSETRESOURCESHAREHANDLENVPROC)load("wglDXSetResourceShareHandleNV");
glad_wglDXOpenDeviceNV = (PFNWGLDXOPENDEVICENVPROC)load("wglDXOpenDeviceNV");
glad_wglDXCloseDeviceNV = (PFNWGLDXCLOSEDEVICENVPROC)load("wglDXCloseDeviceNV");
glad_wglDXRegisterObjectNV = (PFNWGLDXREGISTEROBJECTNVPROC)load("wglDXRegisterObjectNV");
glad_wglDXUnregisterObjectNV = (PFNWGLDXUNREGISTEROBJECTNVPROC)load("wglDXUnregisterObjectNV");
glad_wglDXObjectAccessNV = (PFNWGLDXOBJECTACCESSNVPROC)load("wglDXObjectAccessNV");
glad_wglDXLockObjectsNV = (PFNWGLDXLOCKOBJECTSNVPROC)load("wglDXLockObjectsNV");
glad_wglDXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNVPROC)load("wglDXUnlockObjectsNV");
}
static void load_WGL_NV_copy_image(GLADloadproc load) {
if(!GLAD_WGL_NV_copy_image) return;
glad_wglCopyImageSubDataNV = (PFNWGLCOPYIMAGESUBDATANVPROC)load("wglCopyImageSubDataNV");
}
static void load_WGL_NV_delay_before_swap(GLADloadproc load) {
if(!GLAD_WGL_NV_delay_before_swap) return;
glad_wglDelayBeforeSwapNV = (PFNWGLDELAYBEFORESWAPNVPROC)load("wglDelayBeforeSwapNV");
}
static void load_WGL_NV_gpu_affinity(GLADloadproc load) {
if(!GLAD_WGL_NV_gpu_affinity) return;
glad_wglEnumGpusNV = (PFNWGLENUMGPUSNVPROC)load("wglEnumGpusNV");
glad_wglEnumGpuDevicesNV = (PFNWGLENUMGPUDEVICESNVPROC)load("wglEnumGpuDevicesNV");
glad_wglCreateAffinityDCNV = (PFNWGLCREATEAFFINITYDCNVPROC)load("wglCreateAffinityDCNV");
glad_wglEnumGpusFromAffinityDCNV = (PFNWGLENUMGPUSFROMAFFINITYDCNVPROC)load("wglEnumGpusFromAffinityDCNV");
glad_wglDeleteDCNV = (PFNWGLDELETEDCNVPROC)load("wglDeleteDCNV");
}
static void load_WGL_NV_present_video(GLADloadproc load) {
if(!GLAD_WGL_NV_present_video) return;
glad_wglEnumerateVideoDevicesNV = (PFNWGLENUMERATEVIDEODEVICESNVPROC)load("wglEnumerateVideoDevicesNV");
glad_wglBindVideoDeviceNV = (PFNWGLBINDVIDEODEVICENVPROC)load("wglBindVideoDeviceNV");
glad_wglQueryCurrentContextNV = (PFNWGLQUERYCURRENTCONTEXTNVPROC)load("wglQueryCurrentContextNV");
}
static void load_WGL_NV_swap_group(GLADloadproc load) {
if(!GLAD_WGL_NV_swap_group) return;
glad_wglJoinSwapGroupNV = (PFNWGLJOINSWAPGROUPNVPROC)load("wglJoinSwapGroupNV");
glad_wglBindSwapBarrierNV = (PFNWGLBINDSWAPBARRIERNVPROC)load("wglBindSwapBarrierNV");
glad_wglQuerySwapGroupNV = (PFNWGLQUERYSWAPGROUPNVPROC)load("wglQuerySwapGroupNV");
glad_wglQueryMaxSwapGroupsNV = (PFNWGLQUERYMAXSWAPGROUPSNVPROC)load("wglQueryMaxSwapGroupsNV");
glad_wglQueryFrameCountNV = (PFNWGLQUERYFRAMECOUNTNVPROC)load("wglQueryFrameCountNV");
glad_wglResetFrameCountNV = (PFNWGLRESETFRAMECOUNTNVPROC)load("wglResetFrameCountNV");
}
static void load_WGL_NV_vertex_array_range(GLADloadproc load) {
if(!GLAD_WGL_NV_vertex_array_range) return;
glad_wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC)load("wglAllocateMemoryNV");
glad_wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC)load("wglFreeMemoryNV");
}
static void load_WGL_NV_video_capture(GLADloadproc load) {
if(!GLAD_WGL_NV_video_capture) return;
glad_wglBindVideoCaptureDeviceNV = (PFNWGLBINDVIDEOCAPTUREDEVICENVPROC)load("wglBindVideoCaptureDeviceNV");
glad_wglEnumerateVideoCaptureDevicesNV = (PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC)load("wglEnumerateVideoCaptureDevicesNV");
glad_wglLockVideoCaptureDeviceNV = (PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC)load("wglLockVideoCaptureDeviceNV");
glad_wglQueryVideoCaptureDeviceNV = (PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC)load("wglQueryVideoCaptureDeviceNV");
glad_wglReleaseVideoCaptureDeviceNV = (PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC)load("wglReleaseVideoCaptureDeviceNV");
}
static void load_WGL_NV_video_output(GLADloadproc load) {
if(!GLAD_WGL_NV_video_output) return;
glad_wglGetVideoDeviceNV = (PFNWGLGETVIDEODEVICENVPROC)load("wglGetVideoDeviceNV");
glad_wglReleaseVideoDeviceNV = (PFNWGLRELEASEVIDEODEVICENVPROC)load("wglReleaseVideoDeviceNV");
glad_wglBindVideoImageNV = (PFNWGLBINDVIDEOIMAGENVPROC)load("wglBindVideoImageNV");
glad_wglReleaseVideoImageNV = (PFNWGLRELEASEVIDEOIMAGENVPROC)load("wglReleaseVideoImageNV");
glad_wglSendPbufferToVideoNV = (PFNWGLSENDPBUFFERTOVIDEONVPROC)load("wglSendPbufferToVideoNV");
glad_wglGetVideoInfoNV = (PFNWGLGETVIDEOINFONVPROC)load("wglGetVideoInfoNV");
}
static void load_WGL_OML_sync_control(GLADloadproc load) {
if(!GLAD_WGL_OML_sync_control) return;
glad_wglGetSyncValuesOML = (PFNWGLGETSYNCVALUESOMLPROC)load("wglGetSyncValuesOML");
glad_wglGetMscRateOML = (PFNWGLGETMSCRATEOMLPROC)load("wglGetMscRateOML");
glad_wglSwapBuffersMscOML = (PFNWGLSWAPBUFFERSMSCOMLPROC)load("wglSwapBuffersMscOML");
glad_wglSwapLayerBuffersMscOML = (PFNWGLSWAPLAYERBUFFERSMSCOMLPROC)load("wglSwapLayerBuffersMscOML");
glad_wglWaitForMscOML = (PFNWGLWAITFORMSCOMLPROC)load("wglWaitForMscOML");
glad_wglWaitForSbcOML = (PFNWGLWAITFORSBCOMLPROC)load("wglWaitForSbcOML");
}
static int find_extensionsWGL(void) {
if (!get_exts()) return 0;
GLAD_WGL_3DFX_multisample = has_ext("WGL_3DFX_multisample");
GLAD_WGL_3DL_stereo_control = has_ext("WGL_3DL_stereo_control");
GLAD_WGL_AMD_gpu_association = has_ext("WGL_AMD_gpu_association");
GLAD_WGL_ARB_buffer_region = has_ext("WGL_ARB_buffer_region");
GLAD_WGL_ARB_context_flush_control = has_ext("WGL_ARB_context_flush_control");
GLAD_WGL_ARB_create_context = has_ext("WGL_ARB_create_context");
GLAD_WGL_ARB_create_context_no_error = has_ext("WGL_ARB_create_context_no_error");
GLAD_WGL_ARB_create_context_profile = has_ext("WGL_ARB_create_context_profile");
GLAD_WGL_ARB_create_context_robustness = has_ext("WGL_ARB_create_context_robustness");
GLAD_WGL_ARB_extensions_string = has_ext("WGL_ARB_extensions_string");
GLAD_WGL_ARB_framebuffer_sRGB = has_ext("WGL_ARB_framebuffer_sRGB");
GLAD_WGL_ARB_make_current_read = has_ext("WGL_ARB_make_current_read");
GLAD_WGL_ARB_multisample = has_ext("WGL_ARB_multisample");
GLAD_WGL_ARB_pbuffer = has_ext("WGL_ARB_pbuffer");
GLAD_WGL_ARB_pixel_format = has_ext("WGL_ARB_pixel_format");
GLAD_WGL_ARB_pixel_format_float = has_ext("WGL_ARB_pixel_format_float");
GLAD_WGL_ARB_render_texture = has_ext("WGL_ARB_render_texture");
GLAD_WGL_ARB_robustness_application_isolation = has_ext("WGL_ARB_robustness_application_isolation");
GLAD_WGL_ARB_robustness_share_group_isolation = has_ext("WGL_ARB_robustness_share_group_isolation");
GLAD_WGL_ATI_pixel_format_float = has_ext("WGL_ATI_pixel_format_float");
GLAD_WGL_ATI_render_texture_rectangle = has_ext("WGL_ATI_render_texture_rectangle");
GLAD_WGL_EXT_colorspace = has_ext("WGL_EXT_colorspace");
GLAD_WGL_EXT_create_context_es2_profile = has_ext("WGL_EXT_create_context_es2_profile");
GLAD_WGL_EXT_create_context_es_profile = has_ext("WGL_EXT_create_context_es_profile");
GLAD_WGL_EXT_depth_float = has_ext("WGL_EXT_depth_float");
GLAD_WGL_EXT_display_color_table = has_ext("WGL_EXT_display_color_table");
GLAD_WGL_EXT_extensions_string = has_ext("WGL_EXT_extensions_string");
GLAD_WGL_EXT_framebuffer_sRGB = has_ext("WGL_EXT_framebuffer_sRGB");
GLAD_WGL_EXT_make_current_read = has_ext("WGL_EXT_make_current_read");
GLAD_WGL_EXT_multisample = has_ext("WGL_EXT_multisample");
GLAD_WGL_EXT_pbuffer = has_ext("WGL_EXT_pbuffer");
GLAD_WGL_EXT_pixel_format = has_ext("WGL_EXT_pixel_format");
GLAD_WGL_EXT_pixel_format_packed_float = has_ext("WGL_EXT_pixel_format_packed_float");
GLAD_WGL_EXT_swap_control = has_ext("WGL_EXT_swap_control");
GLAD_WGL_EXT_swap_control_tear = has_ext("WGL_EXT_swap_control_tear");
GLAD_WGL_I3D_digital_video_control = has_ext("WGL_I3D_digital_video_control");
GLAD_WGL_I3D_gamma = has_ext("WGL_I3D_gamma");
GLAD_WGL_I3D_genlock = has_ext("WGL_I3D_genlock");
GLAD_WGL_I3D_image_buffer = has_ext("WGL_I3D_image_buffer");
GLAD_WGL_I3D_swap_frame_lock = has_ext("WGL_I3D_swap_frame_lock");
GLAD_WGL_I3D_swap_frame_usage = has_ext("WGL_I3D_swap_frame_usage");
GLAD_WGL_NV_DX_interop = has_ext("WGL_NV_DX_interop");
GLAD_WGL_NV_DX_interop2 = has_ext("WGL_NV_DX_interop2");
GLAD_WGL_NV_copy_image = has_ext("WGL_NV_copy_image");
GLAD_WGL_NV_delay_before_swap = has_ext("WGL_NV_delay_before_swap");
GLAD_WGL_NV_float_buffer = has_ext("WGL_NV_float_buffer");
GLAD_WGL_NV_gpu_affinity = has_ext("WGL_NV_gpu_affinity");
GLAD_WGL_NV_multigpu_context = has_ext("WGL_NV_multigpu_context");
GLAD_WGL_NV_multisample_coverage = has_ext("WGL_NV_multisample_coverage");
GLAD_WGL_NV_present_video = has_ext("WGL_NV_present_video");
GLAD_WGL_NV_render_depth_texture = has_ext("WGL_NV_render_depth_texture");
GLAD_WGL_NV_render_texture_rectangle = has_ext("WGL_NV_render_texture_rectangle");
GLAD_WGL_NV_swap_group = has_ext("WGL_NV_swap_group");
GLAD_WGL_NV_vertex_array_range = has_ext("WGL_NV_vertex_array_range");
GLAD_WGL_NV_video_capture = has_ext("WGL_NV_video_capture");
GLAD_WGL_NV_video_output = has_ext("WGL_NV_video_output");
GLAD_WGL_OML_sync_control = has_ext("WGL_OML_sync_control");
free_exts();
return 1;
}
static void find_coreWGL(HDC hdc) {
GLADWGLhdc = hdc;
}
int gladLoadWGLLoader(GLADloadproc load, HDC hdc) {
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)load("wglGetExtensionsStringARB");
wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)load("wglGetExtensionsStringEXT");
if(wglGetExtensionsStringARB == NULL && wglGetExtensionsStringEXT == NULL) return 0;
find_coreWGL(hdc);
if (!find_extensionsWGL()) return 0;
load_WGL_3DL_stereo_control(load);
load_WGL_AMD_gpu_association(load);
load_WGL_ARB_buffer_region(load);
load_WGL_ARB_create_context(load);
load_WGL_ARB_extensions_string(load);
load_WGL_ARB_make_current_read(load);
load_WGL_ARB_pbuffer(load);
load_WGL_ARB_pixel_format(load);
load_WGL_ARB_render_texture(load);
load_WGL_EXT_display_color_table(load);
load_WGL_EXT_extensions_string(load);
load_WGL_EXT_make_current_read(load);
load_WGL_EXT_pbuffer(load);
load_WGL_EXT_pixel_format(load);
load_WGL_EXT_swap_control(load);
load_WGL_I3D_digital_video_control(load);
load_WGL_I3D_gamma(load);
load_WGL_I3D_genlock(load);
load_WGL_I3D_image_buffer(load);
load_WGL_I3D_swap_frame_lock(load);
load_WGL_I3D_swap_frame_usage(load);
load_WGL_NV_DX_interop(load);
load_WGL_NV_copy_image(load);
load_WGL_NV_delay_before_swap(load);
load_WGL_NV_gpu_affinity(load);
load_WGL_NV_present_video(load);
load_WGL_NV_swap_group(load);
load_WGL_NV_vertex_array_range(load);
load_WGL_NV_video_capture(load);
load_WGL_NV_video_output(load);
load_WGL_OML_sync_control(load);
return 1;
}