From ce10d9bd02eedf5c14282aeec8fa0d026f33f032 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:32:18 -0600 Subject: [PATCH] Create GL context abstraction layer --- src/xenia/ui/gl/gl.h | 6 +- src/xenia/ui/gl/gl_context.cc | 279 +--------------------------------- src/xenia/ui/gl/gl_context.h | 33 ++-- 3 files changed, 26 insertions(+), 292 deletions(-) diff --git a/src/xenia/ui/gl/gl.h b/src/xenia/ui/gl/gl.h index c2e35a907..796248803 100644 --- a/src/xenia/ui/gl/gl.h +++ b/src/xenia/ui/gl/gl.h @@ -23,6 +23,10 @@ extern "C" GLEWContext* glewGetContext(); // required. typedef struct WGLEWContextStruct WGLEWContext; extern "C" WGLEWContext* wglewGetContext(); -#endif // XE_PLATFORM_WIN32 +#elif XE_PLATFORM_LINUX +typedef struct GLXEWContextStruct GLXEWContext; +extern "C" GLXEWContext* glxewGetContext(); + +#endif #endif // XENIA_UI_GL_GL_H_ diff --git a/src/xenia/ui/gl/gl_context.cc b/src/xenia/ui/gl/gl_context.cc index c908aaf40..9b6c078e6 100644 --- a/src/xenia/ui/gl/gl_context.cc +++ b/src/xenia/ui/gl/gl_context.cc @@ -17,13 +17,10 @@ #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -#include "xenia/base/platform_win.h" #include "xenia/base/profiling.h" #include "xenia/ui/gl/gl_immediate_drawer.h" #include "xenia/ui/window.h" -// TODO(benvanik): move win32 code to _win? -#include "third_party/GL/wglew.h" DEFINE_bool(thread_safe_gl, false, "Only allow one GL context to be active at a time."); @@ -43,14 +40,10 @@ namespace xe { namespace ui { namespace gl { -static std::recursive_mutex global_gl_mutex_; -thread_local GLEWContext* tls_glew_context_ = nullptr; -thread_local WGLEWContext* tls_wglew_context_ = nullptr; -extern "C" GLEWContext* glewGetContext() { return tls_glew_context_; } -extern "C" WGLEWContext* wglewGetContext() { return tls_wglew_context_; } +std::recursive_mutex GLContext::global_gl_mutex_; -void FatalGLError(std::string error) { +void GLContext::FatalGLError(std::string error) { xe::FatalError( error + "\nEnsure you have the latest drivers for your GPU and that it supports " @@ -58,223 +51,11 @@ void FatalGLError(std::string error) { "of supported GPUs."); } -std::unique_ptr GLContext::Create(GraphicsProvider* provider, - Window* target_window, - GLContext* share_context) { - auto context = - std::unique_ptr(new GLContext(provider, target_window)); - if (!context->Initialize(share_context)) { - return nullptr; - } - context->AssertExtensionsPresent(); - return context; -} + GLContext::GLContext(GraphicsProvider* provider, Window* target_window) - : GraphicsContext(provider, target_window) { - glew_context_.reset(new GLEWContext()); - wglew_context_.reset(new WGLEWContext()); -} + : GraphicsContext(provider, target_window) { } -GLContext::~GLContext() { - MakeCurrent(); - blitter_.Shutdown(); - immediate_drawer_.reset(); - ClearCurrent(); - if (glrc_) { - wglDeleteContext(glrc_); - } - if (dc_) { - ReleaseDC(HWND(target_window_->native_handle()), dc_); - } -} - -bool GLContext::Initialize(GLContext* share_context) { - dc_ = GetDC(HWND(target_window_->native_handle())); - - PIXELFORMATDESCRIPTOR pfd = {0}; - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 32; - pfd.cDepthBits = 32; - pfd.iLayerType = PFD_MAIN_PLANE; - int pixel_format = ChoosePixelFormat(dc_, &pfd); - if (!pixel_format) { - FatalGLError("Unable to choose pixel format."); - return false; - } - if (!SetPixelFormat(dc_, pixel_format, &pfd)) { - FatalGLError("Unable to set pixel format."); - return false; - } - - HGLRC temp_context = wglCreateContext(dc_); - if (!temp_context) { - FatalGLError("Unable to create temporary GL context."); - return false; - } - wglMakeCurrent(dc_, temp_context); - - tls_glew_context_ = glew_context_.get(); - tls_wglew_context_ = wglew_context_.get(); - if (glewInit() != GLEW_OK) { - FatalGLError("Unable to initialize GLEW."); - return false; - } - if (wglewInit() != GLEW_OK) { - FatalGLError("Unable to initialize WGLEW."); - return false; - } - - if (!WGLEW_ARB_create_context) { - FatalGLError("WGL_ARG_create_context not supported by GL ICD."); - return false; - } - - if (GLEW_ARB_robustness) { - robust_access_supported_ = true; - } - - int context_flags = 0; - if (FLAGS_gl_debug) { - context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; - } - if (robust_access_supported_) { - context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; - } - - int attrib_list[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, - 4, - WGL_CONTEXT_MINOR_VERSION_ARB, - 5, - WGL_CONTEXT_FLAGS_ARB, - context_flags, - WGL_CONTEXT_PROFILE_MASK_ARB, - WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - robust_access_supported_ ? WGL_LOSE_CONTEXT_ON_RESET_ARB : 0, - 0}; - - glrc_ = wglCreateContextAttribsARB( - dc_, share_context ? share_context->glrc_ : nullptr, attrib_list); - wglMakeCurrent(nullptr, nullptr); - wglDeleteContext(temp_context); - if (!glrc_) { - FatalGLError("Unable to create real GL context."); - return false; - } - - if (!MakeCurrent()) { - FatalGLError("Could not make real GL context current."); - return false; - } - - XELOGI("Successfully created OpenGL context:"); - XELOGI(" GL_VENDOR: %s", glGetString(GL_VENDOR)); - XELOGI(" GL_VERSION: %s", glGetString(GL_VERSION)); - XELOGI(" GL_RENDERER: %s", glGetString(GL_RENDERER)); - XELOGI(" GL_SHADING_LANGUAGE_VERSION: %s", - glGetString(GL_SHADING_LANGUAGE_VERSION)); - - while (glGetError()) { - // Clearing errors. - } - - SetupDebugging(); - - if (!blitter_.Initialize()) { - FatalGLError("Unable to initialize blitter."); - ClearCurrent(); - return false; - } - - immediate_drawer_ = std::make_unique(this); - - ClearCurrent(); - - return true; -} - -std::unique_ptr GLContext::CreateOffscreen( - GraphicsProvider* provider, GLContext* parent_context) { - assert_not_null(parent_context->glrc_); - - HGLRC new_glrc = nullptr; - { - GraphicsContextLock context_lock(parent_context); - - int context_flags = 0; - if (FLAGS_gl_debug) { - context_flags |= WGL_CONTEXT_DEBUG_BIT_ARB; - } - - bool robust_access_supported = parent_context->robust_access_supported_; - if (robust_access_supported) { - context_flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; - } - - int attrib_list[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, - 4, - WGL_CONTEXT_MINOR_VERSION_ARB, - 5, - WGL_CONTEXT_FLAGS_ARB, - context_flags, - WGL_CONTEXT_PROFILE_MASK_ARB, - WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, - WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, - robust_access_supported ? WGL_LOSE_CONTEXT_ON_RESET_ARB : 0, - 0}; - new_glrc = wglCreateContextAttribsARB(parent_context->dc_, - parent_context->glrc_, attrib_list); - if (!new_glrc) { - FatalGLError("Could not create shared context."); - return nullptr; - } - } - - auto new_context = std::unique_ptr( - new GLContext(provider, parent_context->target_window_)); - new_context->glrc_ = new_glrc; - new_context->dc_ = - GetDC(HWND(parent_context->target_window_->native_handle())); - new_context->robust_access_supported_ = - parent_context->robust_access_supported_; - if (!new_context->MakeCurrent()) { - FatalGLError("Could not make new GL context current."); - return nullptr; - } - if (!glGetString(GL_EXTENSIONS)) { - new_context->ClearCurrent(); - FatalGLError("New GL context did not have extensions."); - return nullptr; - } - - if (glewInit() != GLEW_OK) { - new_context->ClearCurrent(); - FatalGLError("Unable to initialize GLEW on shared context."); - return nullptr; - } - if (wglewInit() != GLEW_OK) { - new_context->ClearCurrent(); - FatalGLError("Unable to initialize WGLEW on shared context."); - return nullptr; - } - - new_context->SetupDebugging(); - - if (!new_context->blitter_.Initialize()) { - FatalGLError("Unable to initialize blitter on shared context."); - return nullptr; - } - - new_context->ClearCurrent(); - - return new_context; -} void GLContext::AssertExtensionsPresent() { if (!MakeCurrent()) { @@ -436,39 +217,7 @@ ImmediateDrawer* GLContext::immediate_drawer() { return immediate_drawer_.get(); } -bool GLContext::is_current() { - return tls_glew_context_ == glew_context_.get(); -} -bool GLContext::MakeCurrent() { - SCOPE_profile_cpu_f("gpu"); - if (FLAGS_thread_safe_gl) { - global_gl_mutex_.lock(); - } - - if (!wglMakeCurrent(dc_, glrc_)) { - if (FLAGS_thread_safe_gl) { - global_gl_mutex_.unlock(); - } - FatalGLError("Unable to make GL context current."); - return false; - } - tls_glew_context_ = glew_context_.get(); - tls_wglew_context_ = wglew_context_.get(); - return true; -} - -void GLContext::ClearCurrent() { - if (!FLAGS_disable_gl_context_reset) { - wglMakeCurrent(nullptr, nullptr); - } - tls_glew_context_ = nullptr; - tls_wglew_context_ = nullptr; - - if (FLAGS_thread_safe_gl) { - global_gl_mutex_.unlock(); - } -} bool GLContext::WasLost() { if (!robust_access_supported_) { @@ -484,7 +233,7 @@ bool GLContext::WasLost() { if (status != GL_NO_ERROR) { // Graphics card reset. XELOGE("============= TDR detected on context %p! Context %s =============", - glrc_, status == GL_GUILTY_CONTEXT_RESET ? "guilty" : "innocent"); + handle(), status == GL_GUILTY_CONTEXT_RESET ? "guilty" : "innocent"); context_lost_ = true; return true; } @@ -492,24 +241,6 @@ bool GLContext::WasLost() { return false; } -void GLContext::BeginSwap() { - SCOPE_profile_cpu_i("gpu", "xe::ui::gl::GLContext::BeginSwap"); - float clear_color[] = {238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.0f}; - if (FLAGS_random_clear_color) { - clear_color[0] = - rand() / static_cast(RAND_MAX); // NOLINT(runtime/threadsafe_fn) - clear_color[1] = 1.0f; - clear_color[2] = 0.0f; - clear_color[3] = 1.0f; - } - glClearNamedFramebufferfv(0, GL_COLOR, 0, clear_color); -} - -void GLContext::EndSwap() { - SCOPE_profile_cpu_i("gpu", "xe::ui::gl::GLContext::EndSwap"); - SwapBuffers(dc_); -} - std::unique_ptr GLContext::Capture() { GraphicsContextLock lock(this); diff --git a/src/xenia/ui/gl/gl_context.h b/src/xenia/ui/gl/gl_context.h index a60e2d4ed..7e3a4719a 100644 --- a/src/xenia/ui/gl/gl_context.h +++ b/src/xenia/ui/gl/gl_context.h @@ -13,6 +13,7 @@ #include #include +#include #include "xenia/ui/gl/blitter.h" #include "xenia/ui/gl/gl.h" @@ -44,11 +45,25 @@ class GLContext : public GraphicsContext { void BeginSwap() override; void EndSwap() override; - std::unique_ptr Capture() override; Blitter* blitter() { return &blitter_; } + protected: + Blitter blitter_; + std::unique_ptr immediate_drawer_; + + static std::recursive_mutex global_gl_mutex_; + bool context_lost_ = false; + bool robust_access_supported_ = false; + static void FatalGLError(std::string error); + virtual bool Initialize(GLContext* share_context) = 0; + virtual void* handle() = 0; + GLContext(GraphicsProvider* provider, Window* target_window); + void SetupDebugging(); + void AssertExtensionsPresent(); + void DebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, + GLsizei length, const GLchar* message); private: friend class GLProvider; @@ -59,31 +74,15 @@ class GLContext : public GraphicsContext { GLContext* parent_context); private: - GLContext(GraphicsProvider* provider, Window* target_window); - bool Initialize(GLContext* share_context); - void AssertExtensionsPresent(); - void SetupDebugging(); - void DebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, - GLsizei length, const GLchar* message); static void GLAPIENTRY DebugMessageThunk(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* user_param); - HDC dc_ = nullptr; - HGLRC glrc_ = nullptr; - std::unique_ptr glew_context_; - std::unique_ptr wglew_context_; - - Blitter blitter_; - std::unique_ptr immediate_drawer_; - - bool context_lost_ = false; - bool robust_access_supported_ = false; }; } // namespace gl