mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
Reformat all the things. Have fun with merge conflicts.
This commit is contained in:
@ -7,100 +7,100 @@
|
||||
|
||||
void cInterfaceAGL::Swap()
|
||||
{
|
||||
[cocoaCtx flushBuffer];
|
||||
[cocoaCtx flushBuffer];
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool cInterfaceAGL::Create(void *window_handle, bool core)
|
||||
bool cInterfaceAGL::Create(void* window_handle, bool core)
|
||||
{
|
||||
cocoaWin = reinterpret_cast<NSView*>(window_handle);
|
||||
NSSize size = [cocoaWin frame].size;
|
||||
cocoaWin = reinterpret_cast<NSView*>(window_handle);
|
||||
NSSize size = [cocoaWin frame].size;
|
||||
|
||||
// Enable high-resolution display support.
|
||||
[cocoaWin setWantsBestResolutionOpenGLSurface:YES];
|
||||
// Enable high-resolution display support.
|
||||
[cocoaWin setWantsBestResolutionOpenGLSurface:YES];
|
||||
|
||||
NSWindow *window = [cocoaWin window];
|
||||
NSWindow* window = [cocoaWin window];
|
||||
|
||||
float scale = [window backingScaleFactor];
|
||||
size.width *= scale;
|
||||
size.height *= scale;
|
||||
float scale = [window backingScaleFactor];
|
||||
size.width *= scale;
|
||||
size.height *= scale;
|
||||
|
||||
// Control window size and picture scaling
|
||||
s_backbuffer_width = size.width;
|
||||
s_backbuffer_height = size.height;
|
||||
// Control window size and picture scaling
|
||||
s_backbuffer_width = size.width;
|
||||
s_backbuffer_height = size.height;
|
||||
|
||||
NSOpenGLPixelFormatAttribute attr[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile, core ? NSOpenGLProfileVersion3_2Core : NSOpenGLProfileVersionLegacy, NSOpenGLPFAAccelerated, 0 };
|
||||
NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes: attr];
|
||||
if (fmt == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create pixel format");
|
||||
return false;
|
||||
}
|
||||
NSOpenGLPixelFormatAttribute attr[] = {NSOpenGLPFADoubleBuffer, NSOpenGLPFAOpenGLProfile,
|
||||
core ? NSOpenGLProfileVersion3_2Core :
|
||||
NSOpenGLProfileVersionLegacy,
|
||||
NSOpenGLPFAAccelerated, 0};
|
||||
NSOpenGLPixelFormat* fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
||||
if (fmt == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create pixel format");
|
||||
return false;
|
||||
}
|
||||
|
||||
cocoaCtx = [[NSOpenGLContext alloc] initWithFormat: fmt shareContext: nil];
|
||||
[fmt release];
|
||||
if (cocoaCtx == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create context");
|
||||
return false;
|
||||
}
|
||||
cocoaCtx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:nil];
|
||||
[fmt release];
|
||||
if (cocoaCtx == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create context");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cocoaWin == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create window");
|
||||
return false;
|
||||
}
|
||||
if (cocoaWin == nil)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "failed to create window");
|
||||
return false;
|
||||
}
|
||||
|
||||
[window makeFirstResponder:cocoaWin];
|
||||
[cocoaCtx setView: cocoaWin];
|
||||
[window makeKeyAndOrderFront: nil];
|
||||
[window makeFirstResponder:cocoaWin];
|
||||
[cocoaCtx setView:cocoaWin];
|
||||
[window makeKeyAndOrderFront:nil];
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceAGL::MakeCurrent()
|
||||
{
|
||||
[cocoaCtx makeCurrentContext];
|
||||
return true;
|
||||
[cocoaCtx makeCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceAGL::ClearCurrent()
|
||||
{
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
return true;
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Close backend
|
||||
void cInterfaceAGL::Shutdown()
|
||||
{
|
||||
[cocoaCtx clearDrawable];
|
||||
[cocoaCtx release];
|
||||
cocoaCtx = nil;
|
||||
[cocoaCtx clearDrawable];
|
||||
[cocoaCtx release];
|
||||
cocoaCtx = nil;
|
||||
}
|
||||
|
||||
void cInterfaceAGL::Update()
|
||||
{
|
||||
NSWindow *window = [cocoaWin window];
|
||||
NSSize size = [cocoaWin frame].size;
|
||||
NSWindow* window = [cocoaWin window];
|
||||
NSSize size = [cocoaWin frame].size;
|
||||
|
||||
float scale = [window backingScaleFactor];
|
||||
size.width *= scale;
|
||||
size.height *= scale;
|
||||
float scale = [window backingScaleFactor];
|
||||
size.width *= scale;
|
||||
size.height *= scale;
|
||||
|
||||
if (s_backbuffer_width == size.width &&
|
||||
s_backbuffer_height == size.height)
|
||||
return;
|
||||
if (s_backbuffer_width == size.width && s_backbuffer_height == size.height)
|
||||
return;
|
||||
|
||||
s_backbuffer_width = size.width;
|
||||
s_backbuffer_height = size.height;
|
||||
s_backbuffer_width = size.width;
|
||||
s_backbuffer_height = size.height;
|
||||
|
||||
[cocoaCtx update];
|
||||
[cocoaCtx update];
|
||||
}
|
||||
|
||||
void cInterfaceAGL::SwapInterval(int interval)
|
||||
{
|
||||
[cocoaCtx setValues:(GLint *)&interval forParameter:NSOpenGLCPSwapInterval];
|
||||
[cocoaCtx setValues:(GLint*)&interval forParameter:NSOpenGLCPSwapInterval];
|
||||
}
|
||||
|
||||
|
@ -13,15 +13,15 @@
|
||||
class cInterfaceAGL : public cInterfaceBase
|
||||
{
|
||||
private:
|
||||
NSView* cocoaWin;
|
||||
NSOpenGLContext* cocoaCtx;
|
||||
public:
|
||||
void Swap() override;
|
||||
bool Create(void* window_handle, bool core) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void Update() override;
|
||||
void SwapInterval(int interval) override;
|
||||
NSView* cocoaWin;
|
||||
NSOpenGLContext* cocoaCtx;
|
||||
|
||||
public:
|
||||
void Swap() override;
|
||||
bool Create(void* window_handle, bool core) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void Update() override;
|
||||
void SwapInterval(int interval) override;
|
||||
};
|
||||
|
@ -12,376 +12,364 @@
|
||||
|
||||
#ifndef EGL_KHR_create_context
|
||||
#define EGL_KHR_create_context 1
|
||||
#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
|
||||
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
|
||||
#define EGL_CONTEXT_FLAGS_KHR 0x30FC
|
||||
#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
|
||||
#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
|
||||
#define EGL_CONTEXT_FLAGS_KHR 0x30FC
|
||||
#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
|
||||
#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
|
||||
#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
|
||||
#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
|
||||
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
||||
#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
|
||||
#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF
|
||||
#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
||||
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
||||
#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
|
||||
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
||||
#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
|
||||
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
|
||||
#define EGL_OPENGL_ES3_BIT_KHR 0x00000040
|
||||
#endif /* EGL_KHR_create_context */
|
||||
|
||||
// Show the current FPS
|
||||
void cInterfaceEGL::Swap()
|
||||
{
|
||||
if (egl_surf != EGL_NO_SURFACE)
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
if (egl_surf != EGL_NO_SURFACE)
|
||||
eglSwapBuffers(egl_dpy, egl_surf);
|
||||
}
|
||||
void cInterfaceEGL::SwapInterval(int Interval)
|
||||
{
|
||||
eglSwapInterval(egl_dpy, Interval);
|
||||
eglSwapInterval(egl_dpy, Interval);
|
||||
}
|
||||
|
||||
void* cInterfaceEGL::GetFuncAddress(const std::string& name)
|
||||
{
|
||||
return (void*)eglGetProcAddress(name.c_str());
|
||||
return (void*)eglGetProcAddress(name.c_str());
|
||||
}
|
||||
|
||||
void cInterfaceEGL::DetectMode()
|
||||
{
|
||||
if (s_opengl_mode != GLInterfaceMode::MODE_DETECT)
|
||||
return;
|
||||
if (s_opengl_mode != GLInterfaceMode::MODE_DETECT)
|
||||
return;
|
||||
|
||||
EGLint num_configs;
|
||||
bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false;
|
||||
std::array<int, 3> renderable_types = {
|
||||
EGL_OPENGL_BIT,
|
||||
(1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
EGL_OPENGL_ES2_BIT,
|
||||
};
|
||||
EGLint num_configs;
|
||||
bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false;
|
||||
std::array<int, 3> renderable_types = {
|
||||
EGL_OPENGL_BIT, (1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
EGL_OPENGL_ES2_BIT,
|
||||
};
|
||||
|
||||
for (auto renderable_type : renderable_types)
|
||||
{
|
||||
// attributes for a visual in RGBA format with at least
|
||||
// 8 bits per color
|
||||
int attribs[] = {
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_RENDERABLE_TYPE, renderable_type,
|
||||
EGL_NONE
|
||||
};
|
||||
for (auto renderable_type : renderable_types)
|
||||
{
|
||||
// attributes for a visual in RGBA format with at least
|
||||
// 8 bits per color
|
||||
int attribs[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8, EGL_RENDERABLE_TYPE, renderable_type,
|
||||
EGL_NONE};
|
||||
|
||||
// Get how many configs there are
|
||||
if (!eglChooseConfig( egl_dpy, attribs, nullptr, 0, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
|
||||
continue;
|
||||
}
|
||||
// Get how many configs there are
|
||||
if (!eglChooseConfig(egl_dpy, attribs, nullptr, 0, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
EGLConfig* config = new EGLConfig[num_configs];
|
||||
EGLConfig* config = new EGLConfig[num_configs];
|
||||
|
||||
// Get all the configurations
|
||||
if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
|
||||
delete[] config;
|
||||
continue;
|
||||
}
|
||||
// Get all the configurations
|
||||
if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
|
||||
delete[] config;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_configs; ++i)
|
||||
{
|
||||
EGLint attribVal;
|
||||
bool ret;
|
||||
ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal);
|
||||
if (ret)
|
||||
{
|
||||
if (attribVal & EGL_OPENGL_BIT)
|
||||
supportsGL = true;
|
||||
if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
supportsGLES3 = true;
|
||||
if (attribVal & EGL_OPENGL_ES2_BIT)
|
||||
supportsGLES2 = true;
|
||||
}
|
||||
}
|
||||
delete[] config;
|
||||
}
|
||||
for (int i = 0; i < num_configs; ++i)
|
||||
{
|
||||
EGLint attribVal;
|
||||
bool ret;
|
||||
ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal);
|
||||
if (ret)
|
||||
{
|
||||
if (attribVal & EGL_OPENGL_BIT)
|
||||
supportsGL = true;
|
||||
if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
supportsGLES3 = true;
|
||||
if (attribVal & EGL_OPENGL_ES2_BIT)
|
||||
supportsGLES2 = true;
|
||||
}
|
||||
}
|
||||
delete[] config;
|
||||
}
|
||||
|
||||
if (supportsGL)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
|
||||
else if (supportsGLES3)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3;
|
||||
else if (supportsGLES2)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2;
|
||||
if (supportsGL)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGL;
|
||||
else if (supportsGLES3)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3;
|
||||
else if (supportsGLES2)
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2;
|
||||
|
||||
if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) // Errored before we found a mode
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL
|
||||
if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) // Errored before we found a mode
|
||||
s_opengl_mode = GLInterfaceMode::MODE_OPENGL; // Fall back to OpenGL
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool cInterfaceEGL::Create(void *window_handle, bool core)
|
||||
bool cInterfaceEGL::Create(void* window_handle, bool core)
|
||||
{
|
||||
EGLint egl_major, egl_minor;
|
||||
bool supports_core_profile = false;
|
||||
EGLint egl_major, egl_minor;
|
||||
bool supports_core_profile = false;
|
||||
|
||||
egl_dpy = OpenDisplay();
|
||||
m_host_window = (EGLNativeWindowType) window_handle;
|
||||
m_has_handle = !!window_handle;
|
||||
m_core = core;
|
||||
egl_dpy = OpenDisplay();
|
||||
m_host_window = (EGLNativeWindowType)window_handle;
|
||||
m_has_handle = !!window_handle;
|
||||
m_core = core;
|
||||
|
||||
if (!egl_dpy)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!egl_dpy)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglGetDisplay() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglInitialize() failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!eglInitialize(egl_dpy, &egl_major, &egl_minor))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglInitialize() failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Detection code */
|
||||
EGLint num_configs;
|
||||
/* Detection code */
|
||||
EGLint num_configs;
|
||||
|
||||
DetectMode();
|
||||
DetectMode();
|
||||
|
||||
// attributes for a visual in RGBA format with at least
|
||||
// 8 bits per color
|
||||
int attribs[] = {
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_NONE };
|
||||
// attributes for a visual in RGBA format with at least
|
||||
// 8 bits per color
|
||||
int attribs[] = {EGL_RENDERABLE_TYPE,
|
||||
EGL_OPENGL_ES2_BIT,
|
||||
EGL_RED_SIZE,
|
||||
8,
|
||||
EGL_GREEN_SIZE,
|
||||
8,
|
||||
EGL_BLUE_SIZE,
|
||||
8,
|
||||
EGL_NONE};
|
||||
|
||||
std::vector<EGLint> ctx_attribs;
|
||||
switch (s_opengl_mode)
|
||||
{
|
||||
case GLInterfaceMode::MODE_OPENGL:
|
||||
attribs[1] = EGL_OPENGL_BIT;
|
||||
ctx_attribs = { EGL_NONE };
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES2:
|
||||
attribs[1] = EGL_OPENGL_ES2_BIT;
|
||||
ctx_attribs = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES3:
|
||||
attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
ctx_attribs = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown opengl mode set\n");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
std::vector<EGLint> ctx_attribs;
|
||||
switch (s_opengl_mode)
|
||||
{
|
||||
case GLInterfaceMode::MODE_OPENGL:
|
||||
attribs[1] = EGL_OPENGL_BIT;
|
||||
ctx_attribs = {EGL_NONE};
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES2:
|
||||
attribs[1] = EGL_OPENGL_ES2_BIT;
|
||||
ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES3:
|
||||
attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */
|
||||
ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unknown opengl mode set\n");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!eglChooseConfig( egl_dpy, attribs, &m_config, 1, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
|
||||
return false;
|
||||
}
|
||||
if (!eglChooseConfig(egl_dpy, attribs, &m_config, 1, &num_configs))
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
std::string tmp;
|
||||
std::istringstream buffer(eglQueryString(egl_dpy, EGL_EXTENSIONS));
|
||||
while (buffer >> tmp)
|
||||
{
|
||||
if (tmp == "EGL_KHR_surfaceless_context")
|
||||
m_supports_surfaceless = true;
|
||||
else if (tmp == "EGL_KHR_create_context")
|
||||
supports_core_profile = true;
|
||||
}
|
||||
std::string tmp;
|
||||
std::istringstream buffer(eglQueryString(egl_dpy, EGL_EXTENSIONS));
|
||||
while (buffer >> tmp)
|
||||
{
|
||||
if (tmp == "EGL_KHR_surfaceless_context")
|
||||
m_supports_surfaceless = true;
|
||||
else if (tmp == "EGL_KHR_create_context")
|
||||
supports_core_profile = true;
|
||||
}
|
||||
|
||||
if (supports_core_profile && core && s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
|
||||
{
|
||||
std::array<std::pair<int, int>, 7> versions_to_try =
|
||||
{{
|
||||
{ 4, 5 },
|
||||
{ 4, 4 },
|
||||
{ 4, 3 },
|
||||
{ 4, 2 },
|
||||
{ 4, 1 },
|
||||
{ 4, 0 },
|
||||
{ 3, 3 },
|
||||
}};
|
||||
if (supports_core_profile && core && s_opengl_mode == GLInterfaceMode::MODE_OPENGL)
|
||||
{
|
||||
std::array<std::pair<int, int>, 7> versions_to_try = {{
|
||||
{4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3},
|
||||
}};
|
||||
|
||||
for (const auto& version : versions_to_try)
|
||||
{
|
||||
std::vector<EGLint> core_attribs =
|
||||
{
|
||||
EGL_CONTEXT_MAJOR_VERSION_KHR, version.first,
|
||||
EGL_CONTEXT_MINOR_VERSION_KHR, version.second,
|
||||
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
|
||||
EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR,
|
||||
EGL_NONE
|
||||
};
|
||||
for (const auto& version : versions_to_try)
|
||||
{
|
||||
std::vector<EGLint> core_attribs = {EGL_CONTEXT_MAJOR_VERSION_KHR,
|
||||
version.first,
|
||||
EGL_CONTEXT_MINOR_VERSION_KHR,
|
||||
version.second,
|
||||
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
|
||||
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
|
||||
EGL_CONTEXT_FLAGS_KHR,
|
||||
EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR,
|
||||
EGL_NONE};
|
||||
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]);
|
||||
if (egl_ctx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]);
|
||||
if (egl_ctx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!egl_ctx)
|
||||
{
|
||||
m_core = false;
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]);
|
||||
}
|
||||
if (!egl_ctx)
|
||||
{
|
||||
m_core = false;
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]);
|
||||
}
|
||||
|
||||
if (!egl_ctx)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateContext failed\n");
|
||||
return false;
|
||||
}
|
||||
if (!egl_ctx)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateContext failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateWindowSurface())
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (!CreateWindowSurface())
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<cInterfaceBase> cInterfaceEGL::CreateSharedContext()
|
||||
{
|
||||
std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>();
|
||||
if (!context->Create(this))
|
||||
return nullptr;
|
||||
return context;
|
||||
std::unique_ptr<cInterfaceBase> context = std::make_unique<cInterfaceEGL>();
|
||||
if (!context->Create(this))
|
||||
return nullptr;
|
||||
return context;
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::Create(cInterfaceBase* main_context)
|
||||
{
|
||||
cInterfaceEGL* egl_context = static_cast<cInterfaceEGL*>(main_context);
|
||||
cInterfaceEGL* egl_context = static_cast<cInterfaceEGL*>(main_context);
|
||||
|
||||
egl_dpy = egl_context->egl_dpy;
|
||||
m_core = egl_context->m_core;
|
||||
m_config = egl_context->m_config;
|
||||
m_supports_surfaceless = egl_context->m_supports_surfaceless;
|
||||
m_is_shared = true;
|
||||
m_has_handle = false;
|
||||
egl_dpy = egl_context->egl_dpy;
|
||||
m_core = egl_context->m_core;
|
||||
m_config = egl_context->m_config;
|
||||
m_supports_surfaceless = egl_context->m_supports_surfaceless;
|
||||
m_is_shared = true;
|
||||
m_has_handle = false;
|
||||
|
||||
EGLint ctx_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
EGLint ctx_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
|
||||
switch (egl_context->GetMode())
|
||||
{
|
||||
case GLInterfaceMode::MODE_OPENGL:
|
||||
ctx_attribs[0] = EGL_NONE;
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES2:
|
||||
ctx_attribs[1] = 2;
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES3:
|
||||
ctx_attribs[1] = 3;
|
||||
break;
|
||||
default:
|
||||
INFO_LOG(VIDEO, "Unknown opengl mode set\n");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
switch (egl_context->GetMode())
|
||||
{
|
||||
case GLInterfaceMode::MODE_OPENGL:
|
||||
ctx_attribs[0] = EGL_NONE;
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES2:
|
||||
ctx_attribs[1] = 2;
|
||||
break;
|
||||
case GLInterfaceMode::MODE_OPENGLES3:
|
||||
ctx_attribs[1] = 3;
|
||||
break;
|
||||
default:
|
||||
INFO_LOG(VIDEO, "Unknown opengl mode set\n");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL)
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL)
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, ctx_attribs );
|
||||
if (!egl_ctx)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
egl_ctx = eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, ctx_attribs);
|
||||
if (!egl_ctx)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateWindowSurface())
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (!CreateWindowSurface())
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::CreateWindowSurface()
|
||||
{
|
||||
if (m_has_handle)
|
||||
{
|
||||
EGLNativeWindowType native_window = InitializePlatform(m_host_window, m_config);
|
||||
egl_surf = eglCreateWindowSurface(egl_dpy, m_config, native_window, nullptr);
|
||||
if (!egl_surf)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!m_supports_surfaceless)
|
||||
{
|
||||
EGLint attrib_list[] =
|
||||
{
|
||||
EGL_NONE,
|
||||
};
|
||||
egl_surf = eglCreatePbufferSurface(egl_dpy, m_config, attrib_list);
|
||||
if (!egl_surf)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
egl_surf = EGL_NO_SURFACE;
|
||||
}
|
||||
return true;
|
||||
if (m_has_handle)
|
||||
{
|
||||
EGLNativeWindowType native_window = InitializePlatform(m_host_window, m_config);
|
||||
egl_surf = eglCreateWindowSurface(egl_dpy, m_config, native_window, nullptr);
|
||||
if (!egl_surf)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!m_supports_surfaceless)
|
||||
{
|
||||
EGLint attrib_list[] = {
|
||||
EGL_NONE,
|
||||
};
|
||||
egl_surf = eglCreatePbufferSurface(egl_dpy, m_config, attrib_list);
|
||||
if (!egl_surf)
|
||||
{
|
||||
INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
egl_surf = EGL_NO_SURFACE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cInterfaceEGL::DestroyWindowSurface()
|
||||
{
|
||||
if (egl_surf != EGL_NO_SURFACE && !eglDestroySurface(egl_dpy, egl_surf))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy window surface.");
|
||||
egl_surf = EGL_NO_SURFACE;
|
||||
if (egl_surf != EGL_NO_SURFACE && !eglDestroySurface(egl_dpy, egl_surf))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy window surface.");
|
||||
egl_surf = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::MakeCurrent()
|
||||
{
|
||||
return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx);
|
||||
return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx);
|
||||
}
|
||||
|
||||
void cInterfaceEGL::UpdateHandle(void* window_handle)
|
||||
{
|
||||
m_host_window = (EGLNativeWindowType)window_handle;
|
||||
m_has_handle = !!window_handle;
|
||||
m_host_window = (EGLNativeWindowType)window_handle;
|
||||
m_has_handle = !!window_handle;
|
||||
}
|
||||
|
||||
void cInterfaceEGL::UpdateSurface()
|
||||
{
|
||||
ClearCurrent();
|
||||
DestroyWindowSurface();
|
||||
CreateWindowSurface();
|
||||
MakeCurrent();
|
||||
ClearCurrent();
|
||||
DestroyWindowSurface();
|
||||
CreateWindowSurface();
|
||||
MakeCurrent();
|
||||
}
|
||||
|
||||
bool cInterfaceEGL::ClearCurrent()
|
||||
{
|
||||
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
// Close backend
|
||||
void cInterfaceEGL::Shutdown()
|
||||
{
|
||||
ShutdownPlatform();
|
||||
if (egl_ctx)
|
||||
{
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx))
|
||||
NOTICE_LOG(VIDEO, "Could not release drawing context.");
|
||||
eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (!eglDestroyContext(egl_dpy, egl_ctx))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy drawing context.");
|
||||
DestroyWindowSurface();
|
||||
if (!m_is_shared && !eglTerminate(egl_dpy))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy display connection.");
|
||||
egl_ctx = nullptr;
|
||||
}
|
||||
ShutdownPlatform();
|
||||
if (egl_ctx)
|
||||
{
|
||||
if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx))
|
||||
NOTICE_LOG(VIDEO, "Could not release drawing context.");
|
||||
eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
if (!eglDestroyContext(egl_dpy, egl_ctx))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy drawing context.");
|
||||
DestroyWindowSurface();
|
||||
if (!m_is_shared && !eglTerminate(egl_dpy))
|
||||
NOTICE_LOG(VIDEO, "Could not destroy display connection.");
|
||||
egl_ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -4,44 +4,46 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <string>
|
||||
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
|
||||
class cInterfaceEGL : public cInterfaceBase
|
||||
{
|
||||
private:
|
||||
EGLConfig m_config;
|
||||
bool m_has_handle;
|
||||
EGLNativeWindowType m_host_window;
|
||||
bool m_supports_surfaceless = false;
|
||||
EGLConfig m_config;
|
||||
bool m_has_handle;
|
||||
EGLNativeWindowType m_host_window;
|
||||
bool m_supports_surfaceless = false;
|
||||
|
||||
bool CreateWindowSurface();
|
||||
void DestroyWindowSurface();
|
||||
bool CreateWindowSurface();
|
||||
void DestroyWindowSurface();
|
||||
|
||||
protected:
|
||||
void DetectMode();
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
|
||||
virtual EGLDisplay OpenDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); }
|
||||
virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) { return (EGLNativeWindowType)EGL_DEFAULT_DISPLAY; }
|
||||
virtual void ShutdownPlatform() {}
|
||||
void DetectMode();
|
||||
EGLSurface egl_surf;
|
||||
EGLContext egl_ctx;
|
||||
EGLDisplay egl_dpy;
|
||||
|
||||
virtual EGLDisplay OpenDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); }
|
||||
virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config)
|
||||
{
|
||||
return (EGLNativeWindowType)EGL_DEFAULT_DISPLAY;
|
||||
}
|
||||
virtual void ShutdownPlatform() {}
|
||||
public:
|
||||
void Swap() override;
|
||||
void SwapInterval(int interval) override;
|
||||
void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; }
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void* window_handle, bool core) override;
|
||||
bool Create(cInterfaceBase* main_context) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void UpdateHandle(void* window_handle) override;
|
||||
void UpdateSurface() override;
|
||||
std::unique_ptr<cInterfaceBase> CreateSharedContext() override;
|
||||
void Swap() override;
|
||||
void SwapInterval(int interval) override;
|
||||
void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; }
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void* window_handle, bool core) override;
|
||||
bool Create(cInterfaceBase* main_context) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void UpdateHandle(void* window_handle) override;
|
||||
void UpdateSurface() override;
|
||||
std::unique_ptr<cInterfaceBase> CreateSharedContext() override;
|
||||
};
|
||||
|
@ -6,23 +6,23 @@
|
||||
|
||||
EGLDisplay cInterfaceEGLAndroid::OpenDisplay()
|
||||
{
|
||||
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
return eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config)
|
||||
EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config)
|
||||
{
|
||||
EGLint format;
|
||||
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||
ANativeWindow_setBuffersGeometry(host_window, 0, 0, format);
|
||||
EGLint format;
|
||||
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format);
|
||||
ANativeWindow_setBuffersGeometry(host_window, 0, 0, format);
|
||||
|
||||
const int width = ANativeWindow_getWidth(host_window);
|
||||
const int height = ANativeWindow_getHeight(host_window);
|
||||
GLInterface->SetBackBufferDimensions(width, height);
|
||||
const int width = ANativeWindow_getWidth(host_window);
|
||||
const int height = ANativeWindow_getHeight(host_window);
|
||||
GLInterface->SetBackBufferDimensions(width, height);
|
||||
|
||||
return host_window;
|
||||
return host_window;
|
||||
}
|
||||
|
||||
void cInterfaceEGLAndroid::ShutdownPlatform()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,8 @@
|
||||
class cInterfaceEGLAndroid : public cInterfaceEGL
|
||||
{
|
||||
protected:
|
||||
EGLDisplay OpenDisplay() override;
|
||||
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) override;
|
||||
void ShutdownPlatform() override;
|
||||
EGLDisplay OpenDisplay() override;
|
||||
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config) override;
|
||||
void ShutdownPlatform() override;
|
||||
};
|
||||
|
@ -7,39 +7,39 @@
|
||||
|
||||
EGLDisplay cInterfaceEGLX11::OpenDisplay()
|
||||
{
|
||||
dpy = XOpenDisplay(nullptr);
|
||||
XWindow.Initialize(dpy);
|
||||
return eglGetDisplay(dpy);
|
||||
dpy = XOpenDisplay(nullptr);
|
||||
XWindow.Initialize(dpy);
|
||||
return eglGetDisplay(dpy);
|
||||
}
|
||||
|
||||
EGLNativeWindowType cInterfaceEGLX11::InitializePlatform(EGLNativeWindowType host_window, EGLConfig config)
|
||||
EGLNativeWindowType cInterfaceEGLX11::InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config)
|
||||
{
|
||||
EGLint vid;
|
||||
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid);
|
||||
EGLint vid;
|
||||
eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid);
|
||||
|
||||
XVisualInfo visTemplate;
|
||||
visTemplate.visualid = vid;
|
||||
XVisualInfo visTemplate;
|
||||
visTemplate.visualid = vid;
|
||||
|
||||
XVisualInfo *vi;
|
||||
int nVisuals;
|
||||
vi = XGetVisualInfo(dpy, VisualIDMask, &visTemplate, &nVisuals);
|
||||
XVisualInfo* vi;
|
||||
int nVisuals;
|
||||
vi = XGetVisualInfo(dpy, VisualIDMask, &visTemplate, &nVisuals);
|
||||
|
||||
XWindowAttributes attribs;
|
||||
if (!XGetWindowAttributes(dpy, (Window)host_window, &attribs))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Window attribute retrieval failed");
|
||||
return 0;
|
||||
}
|
||||
XWindowAttributes attribs;
|
||||
if (!XGetWindowAttributes(dpy, (Window)host_window, &attribs))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Window attribute retrieval failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
s_backbuffer_width = attribs.width;
|
||||
s_backbuffer_height = attribs.height;
|
||||
s_backbuffer_width = attribs.width;
|
||||
s_backbuffer_height = attribs.height;
|
||||
|
||||
return (EGLNativeWindowType) XWindow.CreateXWindow((Window) host_window, vi);
|
||||
return (EGLNativeWindowType)XWindow.CreateXWindow((Window)host_window, vi);
|
||||
}
|
||||
|
||||
void cInterfaceEGLX11::ShutdownPlatform()
|
||||
{
|
||||
XWindow.DestroyXWindow();
|
||||
XCloseDisplay(dpy);
|
||||
XWindow.DestroyXWindow();
|
||||
XCloseDisplay(dpy);
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,12 @@
|
||||
class cInterfaceEGLX11 : public cInterfaceEGL
|
||||
{
|
||||
private:
|
||||
cX11Window XWindow;
|
||||
Display *dpy;
|
||||
cX11Window XWindow;
|
||||
Display* dpy;
|
||||
|
||||
protected:
|
||||
EGLDisplay OpenDisplay() override;
|
||||
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) override;
|
||||
void ShutdownPlatform() override;
|
||||
EGLDisplay OpenDisplay() override;
|
||||
EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window,
|
||||
EGLConfig config) override;
|
||||
void ShutdownPlatform() override;
|
||||
};
|
||||
|
@ -26,21 +26,21 @@
|
||||
|
||||
std::unique_ptr<cInterfaceBase> HostGL_CreateGLInterface()
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
return std::make_unique<cInterfaceAGL>();
|
||||
#elif defined(_WIN32)
|
||||
return std::make_unique<cInterfaceWGL>();
|
||||
#elif defined(USE_EGL) && defined(USE_HEADLESS)
|
||||
return std::make_unique<cInterfaceEGL>();
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
#if defined(USE_EGL) && USE_EGL
|
||||
return std::make_unique<cInterfaceEGLX11>();
|
||||
#else
|
||||
return std::make_unique<cInterfaceGLX>();
|
||||
#endif
|
||||
#elif ANDROID
|
||||
return std::make_unique<cInterfaceEGLAndroid>();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
return std::make_unique<cInterfaceAGL>();
|
||||
#elif defined(_WIN32)
|
||||
return std::make_unique<cInterfaceWGL>();
|
||||
#elif defined(USE_EGL) && defined(USE_HEADLESS)
|
||||
return std::make_unique<cInterfaceEGL>();
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
#if defined(USE_EGL) && USE_EGL
|
||||
return std::make_unique<cInterfaceEGLX11>();
|
||||
#else
|
||||
return std::make_unique<cInterfaceGLX>();
|
||||
#endif
|
||||
#elif ANDROID
|
||||
return std::make_unique<cInterfaceEGLAndroid>();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
@ -7,191 +7,195 @@
|
||||
#include "Common/GL/GLInterface/GLX.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
|
||||
typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSPROC)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
||||
typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
|
||||
typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSPROC)(Display*, GLXFBConfig, GLXContext, Bool,
|
||||
const int*);
|
||||
typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int interval);
|
||||
|
||||
static PFNGLXCREATECONTEXTATTRIBSPROC glXCreateContextAttribs = nullptr;
|
||||
static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr;
|
||||
|
||||
static bool s_glxError;
|
||||
static int ctxErrorHandler(Display *dpy, XErrorEvent *ev)
|
||||
static int ctxErrorHandler(Display* dpy, XErrorEvent* ev)
|
||||
{
|
||||
s_glxError = true;
|
||||
return 0;
|
||||
s_glxError = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cInterfaceGLX::SwapInterval(int Interval)
|
||||
{
|
||||
if (glXSwapIntervalSGI)
|
||||
glXSwapIntervalSGI(Interval);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate).");
|
||||
if (glXSwapIntervalSGI)
|
||||
glXSwapIntervalSGI(Interval);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate).");
|
||||
}
|
||||
void* cInterfaceGLX::GetFuncAddress(const std::string& name)
|
||||
{
|
||||
return (void*)glXGetProcAddress((const GLubyte*)name.c_str());
|
||||
return (void*)glXGetProcAddress((const GLubyte*)name.c_str());
|
||||
}
|
||||
|
||||
void cInterfaceGLX::Swap()
|
||||
{
|
||||
glXSwapBuffers(dpy, win);
|
||||
glXSwapBuffers(dpy, win);
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool cInterfaceGLX::Create(void *window_handle, bool core)
|
||||
bool cInterfaceGLX::Create(void* window_handle, bool core)
|
||||
{
|
||||
dpy = XOpenDisplay(nullptr);
|
||||
int screen = DefaultScreen(dpy);
|
||||
dpy = XOpenDisplay(nullptr);
|
||||
int screen = DefaultScreen(dpy);
|
||||
|
||||
// checking glx version
|
||||
int glxMajorVersion, glxMinorVersion;
|
||||
glXQueryVersion(dpy, &glxMajorVersion, &glxMinorVersion);
|
||||
if (glxMajorVersion < 1 || (glxMajorVersion == 1 && glxMinorVersion < 4))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "glX-Version %d.%d detected, but need at least 1.4",
|
||||
glxMajorVersion, glxMinorVersion);
|
||||
return false;
|
||||
}
|
||||
// checking glx version
|
||||
int glxMajorVersion, glxMinorVersion;
|
||||
glXQueryVersion(dpy, &glxMajorVersion, &glxMinorVersion);
|
||||
if (glxMajorVersion < 1 || (glxMajorVersion == 1 && glxMinorVersion < 4))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "glX-Version %d.%d detected, but need at least 1.4", glxMajorVersion,
|
||||
glxMinorVersion);
|
||||
return false;
|
||||
}
|
||||
|
||||
// loading core context creation function
|
||||
glXCreateContextAttribs = (PFNGLXCREATECONTEXTATTRIBSPROC)GetFuncAddress("glXCreateContextAttribsARB");
|
||||
if (!glXCreateContextAttribs)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "glXCreateContextAttribsARB not found, do you support GLX_ARB_create_context?");
|
||||
return false;
|
||||
}
|
||||
// loading core context creation function
|
||||
glXCreateContextAttribs =
|
||||
(PFNGLXCREATECONTEXTATTRIBSPROC)GetFuncAddress("glXCreateContextAttribsARB");
|
||||
if (!glXCreateContextAttribs)
|
||||
{
|
||||
ERROR_LOG(VIDEO,
|
||||
"glXCreateContextAttribsARB not found, do you support GLX_ARB_create_context?");
|
||||
return false;
|
||||
}
|
||||
|
||||
// choosing framebuffer
|
||||
int visual_attribs[] =
|
||||
{
|
||||
GLX_X_RENDERABLE , True,
|
||||
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
|
||||
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE , 8,
|
||||
GLX_GREEN_SIZE , 8,
|
||||
GLX_BLUE_SIZE , 8,
|
||||
GLX_DEPTH_SIZE , 0,
|
||||
GLX_STENCIL_SIZE , 0,
|
||||
GLX_DOUBLEBUFFER , True,
|
||||
None
|
||||
};
|
||||
int fbcount = 0;
|
||||
GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount);
|
||||
if (!fbc || !fbcount)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Failed to retrieve a framebuffer config");
|
||||
return false;
|
||||
}
|
||||
fbconfig = *fbc;
|
||||
XFree(fbc);
|
||||
// choosing framebuffer
|
||||
int visual_attribs[] = {GLX_X_RENDERABLE,
|
||||
True,
|
||||
GLX_DRAWABLE_TYPE,
|
||||
GLX_WINDOW_BIT,
|
||||
GLX_X_VISUAL_TYPE,
|
||||
GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE,
|
||||
8,
|
||||
GLX_GREEN_SIZE,
|
||||
8,
|
||||
GLX_BLUE_SIZE,
|
||||
8,
|
||||
GLX_DEPTH_SIZE,
|
||||
0,
|
||||
GLX_STENCIL_SIZE,
|
||||
0,
|
||||
GLX_DOUBLEBUFFER,
|
||||
True,
|
||||
None};
|
||||
int fbcount = 0;
|
||||
GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount);
|
||||
if (!fbc || !fbcount)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Failed to retrieve a framebuffer config");
|
||||
return false;
|
||||
}
|
||||
fbconfig = *fbc;
|
||||
XFree(fbc);
|
||||
|
||||
// Get an appropriate visual
|
||||
XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, fbconfig);
|
||||
// Get an appropriate visual
|
||||
XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, fbconfig);
|
||||
|
||||
s_glxError = false;
|
||||
XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler);
|
||||
s_glxError = false;
|
||||
XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler);
|
||||
|
||||
// Create a GLX context.
|
||||
// We try to get a 4.0 core profile, else we try 3.3, else try it with anything we get.
|
||||
int context_attribs[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
ctx = nullptr;
|
||||
if (core)
|
||||
{
|
||||
ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
if (core && (!ctx || s_glxError))
|
||||
{
|
||||
int context_attribs_33[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
None
|
||||
};
|
||||
s_glxError = false;
|
||||
ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_33);
|
||||
XSync(dpy, False);
|
||||
// Create a GLX context.
|
||||
// We try to get a 4.0 core profile, else we try 3.3, else try it with anything we get.
|
||||
int context_attribs[] = {GLX_CONTEXT_MAJOR_VERSION_ARB,
|
||||
4,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB,
|
||||
0,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB,
|
||||
GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB,
|
||||
GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
None};
|
||||
ctx = nullptr;
|
||||
if (core)
|
||||
{
|
||||
ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
if (core && (!ctx || s_glxError))
|
||||
{
|
||||
int context_attribs_33[] = {GLX_CONTEXT_MAJOR_VERSION_ARB,
|
||||
3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB,
|
||||
3,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB,
|
||||
GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
|
||||
GLX_CONTEXT_FLAGS_ARB,
|
||||
GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
|
||||
None};
|
||||
s_glxError = false;
|
||||
ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_33);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
if (!ctx || s_glxError)
|
||||
{
|
||||
int context_attribs_legacy[] = {GLX_CONTEXT_MAJOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB,
|
||||
0, None};
|
||||
s_glxError = false;
|
||||
ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_legacy);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
if (!ctx || s_glxError)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Unable to create GL context.");
|
||||
return false;
|
||||
}
|
||||
XSetErrorHandler(oldHandler);
|
||||
|
||||
}
|
||||
if (!ctx || s_glxError)
|
||||
{
|
||||
int context_attribs_legacy[] =
|
||||
{
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 1,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
None
|
||||
};
|
||||
s_glxError = false;
|
||||
ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, context_attribs_legacy);
|
||||
XSync(dpy, False);
|
||||
XWindow.Initialize(dpy);
|
||||
|
||||
}
|
||||
if (!ctx || s_glxError)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Unable to create GL context.");
|
||||
return false;
|
||||
}
|
||||
XSetErrorHandler(oldHandler);
|
||||
Window parent = (Window)window_handle;
|
||||
|
||||
XWindow.Initialize(dpy);
|
||||
XWindowAttributes attribs;
|
||||
if (!XGetWindowAttributes(dpy, parent, &attribs))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Window attribute retrieval failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
Window parent = (Window)window_handle;
|
||||
s_backbuffer_width = attribs.width;
|
||||
s_backbuffer_height = attribs.height;
|
||||
|
||||
XWindowAttributes attribs;
|
||||
if (!XGetWindowAttributes(dpy, parent, &attribs))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Window attribute retrieval failed");
|
||||
return false;
|
||||
}
|
||||
win = XWindow.CreateXWindow(parent, vi);
|
||||
XFree(vi);
|
||||
|
||||
s_backbuffer_width = attribs.width;
|
||||
s_backbuffer_height = attribs.height;
|
||||
|
||||
win = XWindow.CreateXWindow(parent, vi);
|
||||
XFree(vi);
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceGLX::MakeCurrent()
|
||||
{
|
||||
bool success = glXMakeCurrent(dpy, win, ctx);
|
||||
if (success)
|
||||
{
|
||||
// load this function based on the current bound context
|
||||
glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)GLInterface->GetFuncAddress("glXSwapIntervalSGI");
|
||||
}
|
||||
return success;
|
||||
bool success = glXMakeCurrent(dpy, win, ctx);
|
||||
if (success)
|
||||
{
|
||||
// load this function based on the current bound context
|
||||
glXSwapIntervalSGI =
|
||||
(PFNGLXSWAPINTERVALSGIPROC)GLInterface->GetFuncAddress("glXSwapIntervalSGI");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool cInterfaceGLX::ClearCurrent()
|
||||
{
|
||||
return glXMakeCurrent(dpy, None, nullptr);
|
||||
return glXMakeCurrent(dpy, None, nullptr);
|
||||
}
|
||||
|
||||
|
||||
// Close backend
|
||||
void cInterfaceGLX::Shutdown()
|
||||
{
|
||||
XWindow.DestroyXWindow();
|
||||
if (ctx)
|
||||
{
|
||||
glXDestroyContext(dpy, ctx);
|
||||
XCloseDisplay(dpy);
|
||||
ctx = nullptr;
|
||||
}
|
||||
XWindow.DestroyXWindow();
|
||||
if (ctx)
|
||||
{
|
||||
glXDestroyContext(dpy, ctx);
|
||||
XCloseDisplay(dpy);
|
||||
ctx = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,27 +4,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <GL/glx.h>
|
||||
#include <string>
|
||||
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/GL/GLInterface/X11_Util.h"
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
|
||||
class cInterfaceGLX : public cInterfaceBase
|
||||
{
|
||||
private:
|
||||
cX11Window XWindow;
|
||||
Display *dpy;
|
||||
Window win;
|
||||
GLXContext ctx;
|
||||
GLXFBConfig fbconfig;
|
||||
cX11Window XWindow;
|
||||
Display* dpy;
|
||||
Window win;
|
||||
GLXContext ctx;
|
||||
GLXFBConfig fbconfig;
|
||||
|
||||
public:
|
||||
friend class cX11Window;
|
||||
void SwapInterval(int Interval) override;
|
||||
void Swap() override;
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void *window_handle, bool core) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
friend class cX11Window;
|
||||
void SwapInterval(int Interval) override;
|
||||
void Swap() override;
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void* window_handle, bool core) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
};
|
||||
|
@ -5,174 +5,174 @@
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/GL/GLInterface/WGL.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
|
||||
static HDC hDC = nullptr; // Private GDI Device Context
|
||||
static HGLRC hRC = nullptr; // Permanent Rendering Context
|
||||
static HINSTANCE dllHandle = nullptr; // Handle to OpenGL32.dll
|
||||
static HDC hDC = nullptr; // Private GDI Device Context
|
||||
static HGLRC hRC = nullptr; // Permanent Rendering Context
|
||||
static HINSTANCE dllHandle = nullptr; // Handle to OpenGL32.dll
|
||||
|
||||
// typedef from wglext.h
|
||||
typedef BOOL(WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
|
||||
typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval);
|
||||
static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr;
|
||||
|
||||
void cInterfaceWGL::SwapInterval(int Interval)
|
||||
{
|
||||
if (wglSwapIntervalEXT)
|
||||
wglSwapIntervalEXT(Interval);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate).");
|
||||
if (wglSwapIntervalEXT)
|
||||
wglSwapIntervalEXT(Interval);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate).");
|
||||
}
|
||||
void cInterfaceWGL::Swap()
|
||||
{
|
||||
SwapBuffers(hDC);
|
||||
SwapBuffers(hDC);
|
||||
}
|
||||
|
||||
void* cInterfaceWGL::GetFuncAddress(const std::string& name)
|
||||
{
|
||||
void* func = (void*)wglGetProcAddress((LPCSTR)name.c_str());
|
||||
if (func == nullptr)
|
||||
func = (void*)GetProcAddress(dllHandle, (LPCSTR)name.c_str());
|
||||
return func;
|
||||
void* func = (void*)wglGetProcAddress((LPCSTR)name.c_str());
|
||||
if (func == nullptr)
|
||||
func = (void*)GetProcAddress(dllHandle, (LPCSTR)name.c_str());
|
||||
return func;
|
||||
}
|
||||
|
||||
// Draw messages on top of the screen
|
||||
bool cInterfaceWGL::PeekMessages()
|
||||
{
|
||||
// TODO: peekmessage
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
// TODO: peekmessage
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool cInterfaceWGL::Create(void *window_handle, bool core)
|
||||
bool cInterfaceWGL::Create(void* window_handle, bool core)
|
||||
{
|
||||
if (window_handle == nullptr)
|
||||
return false;
|
||||
if (window_handle == nullptr)
|
||||
return false;
|
||||
|
||||
HWND window_handle_reified = reinterpret_cast<HWND>(window_handle);
|
||||
RECT window_rect = {0};
|
||||
HWND window_handle_reified = reinterpret_cast<HWND>(window_handle);
|
||||
RECT window_rect = {0};
|
||||
|
||||
if (!GetClientRect(window_handle_reified, &window_rect))
|
||||
return false;
|
||||
if (!GetClientRect(window_handle_reified, &window_rect))
|
||||
return false;
|
||||
|
||||
// Control window size and picture scaling
|
||||
int twidth = (window_rect.right - window_rect.left);
|
||||
int theight = (window_rect.bottom - window_rect.top);
|
||||
s_backbuffer_width = twidth;
|
||||
s_backbuffer_height = theight;
|
||||
// Control window size and picture scaling
|
||||
int twidth = (window_rect.right - window_rect.left);
|
||||
int theight = (window_rect.bottom - window_rect.top);
|
||||
s_backbuffer_width = twidth;
|
||||
s_backbuffer_height = theight;
|
||||
|
||||
m_window_handle = window_handle_reified;
|
||||
m_window_handle = window_handle_reified;
|
||||
|
||||
dllHandle = LoadLibrary(TEXT("OpenGL32.dll"));
|
||||
dllHandle = LoadLibrary(TEXT("OpenGL32.dll"));
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
|
||||
1, // Version Number
|
||||
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
||||
PFD_DOUBLEBUFFER, // Must Support Double Buffering
|
||||
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||
32, // Select Our Color Depth
|
||||
0, 0, 0, 0, 0, 0, // Color Bits Ignored
|
||||
0, // 8bit Alpha Buffer
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
0, // 0Bit Z-Buffer (Depth Buffer)
|
||||
0, // 0bit Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 // Layer Masks Ignored
|
||||
};
|
||||
PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
|
||||
1, // Version Number
|
||||
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
||||
PFD_DOUBLEBUFFER, // Must Support Double Buffering
|
||||
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||
32, // Select Our Color Depth
|
||||
0,
|
||||
0, 0, 0, 0, 0, // Color Bits Ignored
|
||||
0, // 8bit Alpha Buffer
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
0, // 0Bit Z-Buffer (Depth Buffer)
|
||||
0, // 0bit Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 // Layer Masks Ignored
|
||||
};
|
||||
|
||||
int PixelFormat; // Holds The Results After Searching For A Match
|
||||
int PixelFormat; // Holds The Results After Searching For A Match
|
||||
|
||||
if (!(hDC = GetDC(window_handle_reified)))
|
||||
{
|
||||
PanicAlert("(1) Can't create an OpenGL Device context. Fail.");
|
||||
return false;
|
||||
}
|
||||
if (!(hDC = GetDC(window_handle_reified)))
|
||||
{
|
||||
PanicAlert("(1) Can't create an OpenGL Device context. Fail.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
|
||||
{
|
||||
PanicAlert("(2) Can't find a suitable PixelFormat.");
|
||||
return false;
|
||||
}
|
||||
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
|
||||
{
|
||||
PanicAlert("(2) Can't find a suitable PixelFormat.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(hDC, PixelFormat, &pfd))
|
||||
{
|
||||
PanicAlert("(3) Can't set the PixelFormat.");
|
||||
return false;
|
||||
}
|
||||
if (!SetPixelFormat(hDC, PixelFormat, &pfd))
|
||||
{
|
||||
PanicAlert("(3) Can't set the PixelFormat.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(hRC = wglCreateContext(hDC)))
|
||||
{
|
||||
PanicAlert("(4) Can't create an OpenGL rendering context.");
|
||||
return false;
|
||||
}
|
||||
if (!(hRC = wglCreateContext(hDC)))
|
||||
{
|
||||
PanicAlert("(4) Can't create an OpenGL rendering context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cInterfaceWGL::MakeCurrent()
|
||||
{
|
||||
bool success = wglMakeCurrent(hDC, hRC) ? true : false;
|
||||
if (success)
|
||||
{
|
||||
// Grab the swap interval function pointer
|
||||
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)GLInterface->GetFuncAddress("wglSwapIntervalEXT");
|
||||
}
|
||||
return success;
|
||||
bool success = wglMakeCurrent(hDC, hRC) ? true : false;
|
||||
if (success)
|
||||
{
|
||||
// Grab the swap interval function pointer
|
||||
wglSwapIntervalEXT =
|
||||
(PFNWGLSWAPINTERVALEXTPROC)GLInterface->GetFuncAddress("wglSwapIntervalEXT");
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool cInterfaceWGL::ClearCurrent()
|
||||
{
|
||||
return wglMakeCurrent(hDC, nullptr) ? true : false;
|
||||
return wglMakeCurrent(hDC, nullptr) ? true : false;
|
||||
}
|
||||
|
||||
// Update window width, size and etc. Called from Render.cpp
|
||||
void cInterfaceWGL::Update()
|
||||
{
|
||||
RECT rcWindow;
|
||||
GetClientRect(m_window_handle, &rcWindow);
|
||||
RECT rcWindow;
|
||||
GetClientRect(m_window_handle, &rcWindow);
|
||||
|
||||
// Get the new window width and height
|
||||
s_backbuffer_width = (rcWindow.right - rcWindow.left);
|
||||
s_backbuffer_height = (rcWindow.bottom - rcWindow.top);
|
||||
// Get the new window width and height
|
||||
s_backbuffer_width = (rcWindow.right - rcWindow.left);
|
||||
s_backbuffer_height = (rcWindow.bottom - rcWindow.top);
|
||||
}
|
||||
|
||||
// Close backend
|
||||
void cInterfaceWGL::Shutdown()
|
||||
{
|
||||
if (hRC)
|
||||
{
|
||||
if (!wglMakeCurrent(nullptr, nullptr))
|
||||
NOTICE_LOG(VIDEO, "Could not release drawing context.");
|
||||
if (hRC)
|
||||
{
|
||||
if (!wglMakeCurrent(nullptr, nullptr))
|
||||
NOTICE_LOG(VIDEO, "Could not release drawing context.");
|
||||
|
||||
if (!wglDeleteContext(hRC))
|
||||
ERROR_LOG(VIDEO, "Attempt to release rendering context failed.");
|
||||
if (!wglDeleteContext(hRC))
|
||||
ERROR_LOG(VIDEO, "Attempt to release rendering context failed.");
|
||||
|
||||
hRC = nullptr;
|
||||
}
|
||||
hRC = nullptr;
|
||||
}
|
||||
|
||||
if (hDC && !ReleaseDC(m_window_handle, hDC))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Attempt to release device context failed.");
|
||||
hDC = nullptr;
|
||||
}
|
||||
FreeLibrary(dllHandle);
|
||||
if (hDC && !ReleaseDC(m_window_handle, hDC))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Attempt to release device context failed.");
|
||||
hDC = nullptr;
|
||||
}
|
||||
FreeLibrary(dllHandle);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,17 +10,17 @@
|
||||
class cInterfaceWGL : public cInterfaceBase
|
||||
{
|
||||
public:
|
||||
void SwapInterval(int interval) override;
|
||||
void Swap() override;
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void* window_handle, bool core) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
void SwapInterval(int interval) override;
|
||||
void Swap() override;
|
||||
void* GetFuncAddress(const std::string& name) override;
|
||||
bool Create(void* window_handle, bool core) override;
|
||||
bool MakeCurrent() override;
|
||||
bool ClearCurrent() override;
|
||||
void Shutdown() override;
|
||||
|
||||
void Update() override;
|
||||
bool PeekMessages() override;
|
||||
void Update() override;
|
||||
bool PeekMessages() override;
|
||||
|
||||
private:
|
||||
HWND m_window_handle = nullptr;
|
||||
HWND m_window_handle = nullptr;
|
||||
};
|
||||
|
@ -2,73 +2,71 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Common/Thread.h"
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/GL/GLInterface/X11_Util.h"
|
||||
#include "Common/GL/GLInterfaceBase.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/Thread.h"
|
||||
|
||||
void cX11Window::Initialize(Display *_dpy)
|
||||
void cX11Window::Initialize(Display* _dpy)
|
||||
{
|
||||
dpy = _dpy;
|
||||
dpy = _dpy;
|
||||
}
|
||||
|
||||
Window cX11Window::CreateXWindow(Window parent, XVisualInfo *vi)
|
||||
Window cX11Window::CreateXWindow(Window parent, XVisualInfo* vi)
|
||||
{
|
||||
XSetWindowAttributes attr;
|
||||
XSetWindowAttributes attr;
|
||||
|
||||
colormap = XCreateColormap(dpy, parent, vi->visual, AllocNone);
|
||||
colormap = XCreateColormap(dpy, parent, vi->visual, AllocNone);
|
||||
|
||||
// Setup window attributes
|
||||
attr.colormap = colormap;
|
||||
// Setup window attributes
|
||||
attr.colormap = colormap;
|
||||
|
||||
XWindowAttributes attribs;
|
||||
if (!XGetWindowAttributes(dpy, parent, &attribs))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Window attribute retrieval failed");
|
||||
return 0;
|
||||
}
|
||||
XWindowAttributes attribs;
|
||||
if (!XGetWindowAttributes(dpy, parent, &attribs))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Window attribute retrieval failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create the window
|
||||
win = XCreateWindow(dpy, parent,
|
||||
0, 0, attribs.width, attribs.height, 0,
|
||||
vi->depth, InputOutput, vi->visual,
|
||||
CWColormap, &attr);
|
||||
XSelectInput(dpy, parent, StructureNotifyMask);
|
||||
XMapWindow(dpy, win);
|
||||
XSync(dpy, True);
|
||||
// Create the window
|
||||
win = XCreateWindow(dpy, parent, 0, 0, attribs.width, attribs.height, 0, vi->depth, InputOutput,
|
||||
vi->visual, CWColormap, &attr);
|
||||
XSelectInput(dpy, parent, StructureNotifyMask);
|
||||
XMapWindow(dpy, win);
|
||||
XSync(dpy, True);
|
||||
|
||||
xEventThread = std::thread(&cX11Window::XEventThread, this);
|
||||
xEventThread = std::thread(&cX11Window::XEventThread, this);
|
||||
|
||||
return win;
|
||||
return win;
|
||||
}
|
||||
|
||||
void cX11Window::DestroyXWindow(void)
|
||||
{
|
||||
XUnmapWindow(dpy, win);
|
||||
win = 0;
|
||||
if (xEventThread.joinable())
|
||||
xEventThread.join();
|
||||
XFreeColormap(dpy, colormap);
|
||||
XUnmapWindow(dpy, win);
|
||||
win = 0;
|
||||
if (xEventThread.joinable())
|
||||
xEventThread.join();
|
||||
XFreeColormap(dpy, colormap);
|
||||
}
|
||||
|
||||
void cX11Window::XEventThread()
|
||||
{
|
||||
while (win)
|
||||
{
|
||||
XEvent event;
|
||||
for (int num_events = XPending(dpy); num_events > 0; num_events--)
|
||||
{
|
||||
XNextEvent(dpy, &event);
|
||||
switch (event.type)
|
||||
{
|
||||
case ConfigureNotify:
|
||||
XResizeWindow(dpy, win, event.xconfigure.width, event.xconfigure.height);
|
||||
GLInterface->SetBackBufferDimensions(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Common::SleepCurrentThread(20);
|
||||
}
|
||||
while (win)
|
||||
{
|
||||
XEvent event;
|
||||
for (int num_events = XPending(dpy); num_events > 0; num_events--)
|
||||
{
|
||||
XNextEvent(dpy, &event);
|
||||
switch (event.type)
|
||||
{
|
||||
case ConfigureNotify:
|
||||
XResizeWindow(dpy, win, event.xconfigure.width, event.xconfigure.height);
|
||||
GLInterface->SetBackBufferDimensions(event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Common::SleepCurrentThread(20);
|
||||
}
|
||||
}
|
||||
|
@ -4,23 +4,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
class cX11Window
|
||||
{
|
||||
private:
|
||||
void XEventThread();
|
||||
std::thread xEventThread;
|
||||
Colormap colormap;
|
||||
public:
|
||||
void Initialize(Display *dpy);
|
||||
Window CreateXWindow(Window parent, XVisualInfo *vi);
|
||||
void DestroyXWindow();
|
||||
void XEventThread();
|
||||
std::thread xEventThread;
|
||||
Colormap colormap;
|
||||
|
||||
Display *dpy;
|
||||
Window win;
|
||||
public:
|
||||
void Initialize(Display* dpy);
|
||||
Window CreateXWindow(Window parent, XVisualInfo* vi);
|
||||
void DestroyXWindow();
|
||||
|
||||
Display* dpy;
|
||||
Window win;
|
||||
};
|
||||
|
Reference in New Issue
Block a user