From fb8d83b9b5e983eaa419a469be99e77d9059191d Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 02:33:12 -0600 Subject: [PATCH 01/38] Add compile and link flags for Linux platform (X11, vulkan, gtk, etc) --- premake5.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/premake5.lua b/premake5.lua index 8626ec7fb..6f015fc54 100644 --- a/premake5.lua +++ b/premake5.lua @@ -90,6 +90,14 @@ filter("platforms:Linux") }) links({ "pthread", + "lz4", + "X11", + "GL", + "GLEW", + "vulkan", + }) + linkoptions({ + "`pkg-config --libs gtk+-3.0`", }) filter({"platforms:Linux", "language:C++", "toolset:gcc"}) @@ -102,10 +110,13 @@ filter({"platforms:Linux", "language:C++", "toolset:gcc"}) filter({"platforms:Linux", "language:C++", "toolset:clang"}) buildoptions({ "-std=c++14", +<<<<<<< HEAD "-stdlib=libc++", +======= +-- "-stdlib=libc++", -- Seems to happier using gcc's libc++ +>>>>>>> d50e6f18... Add Linux build params for gtk, libvulkan, etc }) links({ - "c++", }) filter("platforms:Windows") From 69e818555d49630ddce5358e1c7b06bccf1c8570 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:27:37 -0600 Subject: [PATCH 02/38] Filter resource file from non-windows platforms --- src/xenia/app/premake5.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 26b30fc5b..141450980 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -40,9 +40,10 @@ project("xenia-app") "xenia_main.cc", "../base/main_"..platform_suffix..".cc", }) - files({ - "main_resources.rc", - }) + filter("platforms:Windows") + files({ + "main_resources.rc", + }) resincludedirs({ project_root, }) From ce10d9bd02eedf5c14282aeec8fa0d026f33f032 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:32:18 -0600 Subject: [PATCH 03/38] 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 From a63c9458cd7f249177834a74fa22b540e95eade8 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:32:46 -0600 Subject: [PATCH 04/38] Implement GL context for windows platform --- src/xenia/ui/gl/gl_context.cc | 1 + src/xenia/ui/gl/gl_context.h | 21 +- src/xenia/ui/gl/gl_context_win.cc | 320 ++++++++++++++++++++++++++++ src/xenia/ui/gl/gl_context_win.h | 69 ++++++ src/xenia/ui/gl/gl_context_x11.cc | 336 ++++++++++++++++++++++++++++++ src/xenia/ui/gl/gl_context_x11.h | 71 +++++++ 6 files changed, 810 insertions(+), 8 deletions(-) create mode 100644 src/xenia/ui/gl/gl_context_win.cc create mode 100644 src/xenia/ui/gl/gl_context_win.h create mode 100644 src/xenia/ui/gl/gl_context_x11.cc create mode 100644 src/xenia/ui/gl/gl_context_x11.h diff --git a/src/xenia/ui/gl/gl_context.cc b/src/xenia/ui/gl/gl_context.cc index 9b6c078e6..24c4f75ce 100644 --- a/src/xenia/ui/gl/gl_context.cc +++ b/src/xenia/ui/gl/gl_context.cc @@ -56,6 +56,7 @@ void GLContext::FatalGLError(std::string error) { GLContext::GLContext(GraphicsProvider* provider, Window* target_window) : GraphicsContext(provider, target_window) { } +GLContext::~GLContext() {} void GLContext::AssertExtensionsPresent() { if (!MakeCurrent()) { diff --git a/src/xenia/ui/gl/gl_context.h b/src/xenia/ui/gl/gl_context.h index 7e3a4719a..b0cb3a1be 100644 --- a/src/xenia/ui/gl/gl_context.h +++ b/src/xenia/ui/gl/gl_context.h @@ -21,9 +21,14 @@ DECLARE_bool(thread_safe_gl); -// TODO(benvanik): hide Win32 stuff. -typedef struct HDC__* HDC; -typedef struct HGLRC__* HGLRC; +DECLARE_bool(disable_gl_context_reset); + +DECLARE_bool(random_clear_color); + +DECLARE_bool(gl_debug); +DECLARE_bool(gl_debug_output); +DECLARE_bool(gl_debug_output_synchronous); + namespace xe { namespace ui { @@ -38,13 +43,13 @@ class GLContext : public GraphicsContext { ImmediateDrawer* immediate_drawer() override; - bool is_current() override; - bool MakeCurrent() override; - void ClearCurrent() override; + bool is_current() = 0; + bool MakeCurrent() = 0; + void ClearCurrent() = 0; bool WasLost() override; - void BeginSwap() override; - void EndSwap() override; + void BeginSwap() = 0; + void EndSwap() = 0; std::unique_ptr Capture() override; Blitter* blitter() { return &blitter_; } diff --git a/src/xenia/ui/gl/gl_context_win.cc b/src/xenia/ui/gl/gl_context_win.cc new file mode 100644 index 000000000..c48e4a55e --- /dev/null +++ b/src/xenia/ui/gl/gl_context_win.cc @@ -0,0 +1,320 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/gl/gl_context_win.h" + +#include + +#include +#include + +#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" + +#include "third_party/GL/wglew.h" + + +namespace xe { +namespace ui { +namespace gl { + + +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::unique_ptr GLContext::Create(GraphicsProvider* provider, + Window* target_window, + GLContext* share_context) { + auto context = + std::unique_ptr(new WGLContext(provider, target_window)); + if (!context->Initialize(share_context)) { + return nullptr; + } + context->AssertExtensionsPresent(); + return context; +} + + +std::unique_ptr GLContext::CreateOffscreen( + GraphicsProvider* provider, GLContext* parent_context) { + return WGLContext::CreateOffscreen(provider, + static_cast(parent_context)); +} + +WGLContext::WGLContext(GraphicsProvider* provider, Window* target_window) + : GLContext(provider, target_window) { + glew_context_.reset(new GLEWContext()); + wglew_context_.reset(new WGLEWContext()); +} + +WGLContext::~WGLContext() { + MakeCurrent(); + blitter_.Shutdown(); + immediate_drawer_.reset(); + ClearCurrent(); + if (glrc_) { + wglDeleteContext(glrc_); + } + if (dc_) { + ReleaseDC(HWND(target_window_->native_handle()), dc_); + } +} + +bool WGLContext::Initialize(GLContext* share_context_) { + WGLContext* share_context = static_cast(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 WGLContext::CreateOffscreen( + GraphicsProvider* provider, WGLContext* 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 WGLContext(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; +} + +bool WGLContext::is_current() { + return tls_glew_context_ == glew_context_.get(); +} + +bool WGLContext::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 WGLContext::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(); + } +} + + +void WGLContext::BeginSwap() { + SCOPE_profile_cpu_i("gpu", "xe::ui::gl::WGLContext::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 WGLContext::EndSwap() { + SCOPE_profile_cpu_i("gpu", "xe::ui::gl::WGLContext::EndSwap"); + SwapBuffers(dc_); +} + +} // namespace gl +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/gl/gl_context_win.h b/src/xenia/ui/gl/gl_context_win.h new file mode 100644 index 000000000..392418f81 --- /dev/null +++ b/src/xenia/ui/gl/gl_context_win.h @@ -0,0 +1,69 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_GL_WGL_CONTEXT_H_ +#define XENIA_UI_GL_WGL_CONTEXT_H_ + +#include + +#include + +#include "xenia/ui/gl/gl_context.h" +#include "xenia/ui/gl/blitter.h" +#include "xenia/ui/gl/gl.h" +#include "xenia/ui/graphics_context.h" + +typedef struct HDC__* HDC; +typedef struct HGLRC__* HGLRC; + +namespace xe { +namespace ui { +namespace gl { + +class GLImmediateDrawer; +class GLProvider; + +class WGLContext : public GLContext { + public: + ~WGLContext() override; + + + bool is_current() override; + bool MakeCurrent() override; + void ClearCurrent() override; + + void BeginSwap() override; + void EndSwap() override; + + + protected: + friend class GLContext; + WGLContext(GraphicsProvider* provider, Window* target_window); + static std::unique_ptr CreateOffscreen(GraphicsProvider* provider, + WGLContext* parent_context); + + bool Initialize(GLContext* share_context) override; + void* handle() override {return glrc_;}; + + private: + + + HDC dc_ = nullptr; + HGLRC glrc_ = nullptr; + + std::unique_ptr glew_context_; + std::unique_ptr wglew_context_; + +}; + +} // namespace gl +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_GL_GL_CONTEXT_H_ diff --git a/src/xenia/ui/gl/gl_context_x11.cc b/src/xenia/ui/gl/gl_context_x11.cc new file mode 100644 index 000000000..5c582b92d --- /dev/null +++ b/src/xenia/ui/gl/gl_context_x11.cc @@ -0,0 +1,336 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/gl/gl_context_x11.h" + +#include + +#include +#include + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" +#include "xenia/base/math.h" +#include "xenia/base/platform_linux.h" +#include "xenia/base/profiling.h" +#include "xenia/ui/gl/gl_immediate_drawer.h" +#include "xenia/ui/window.h" +#include "third_party/GL/glxew.h" +#include + +namespace xe { +namespace ui { +namespace gl { + + +DEFINE_bool(disable_gl_context_reset, false, + "Do not aggressively reset the GL context (helps with capture " + "programs such as OBS or FRAPS)."); +DEFINE_bool(gl_debug, false, "Enable OpenGL debug validation layer."); + +thread_local GLEWContext* tls_glew_context_ = nullptr; +thread_local GLXEWContext* tls_glxew_context_ = nullptr; +extern "C" GLEWContext* glewGetContext() { return tls_glew_context_; } +extern "C" GLXEWContext* glxewGetContext() { return tls_glxew_context_; } + + +std::unique_ptr GLContext::Create(GraphicsProvider* provider, + Window* target_window, + GLContext* share_context) { + auto context = + std::unique_ptr(new GLXContext(provider, target_window)); + if (!context->Initialize(share_context)) { + return nullptr; + } + context->AssertExtensionsPresent(); + return context; +} + + +std::unique_ptr GLContext::CreateOffscreen( + GraphicsProvider* provider, GLContext* parent_context) { + return GLXContext::CreateOffscreen(provider, + dynamic_cast(parent_context)); +} + +GLXContext::GLXContext(GraphicsProvider* provider, Window* target_window) + : GLContext(provider, target_window) { + glew_context_.reset(new GLEWContext()); + glxew_context_.reset(new GLXEWContext()); +} + +GLXContext::~GLXContext() { + MakeCurrent(); + blitter_.Shutdown(); + immediate_drawer_.reset(); + ClearCurrent(); + if (glx_context_) { + glXDestroyContext(disp_, glx_context_); + } + if (draw_area_) { + gtk_widget_destroy(draw_area_); + } +} + + + +bool GLXContext::Initialize(GLContext* share_context) { + GtkWidget* window = GTK_WIDGET(target_window_->native_handle()); + GtkWidget* draw_area = gtk_drawing_area_new(); + int32_t width; + int32_t height; + gtk_window_get_size(GTK_WINDOW(window), &width, &height); + gtk_widget_set_size_request(draw_area, width, height); + gtk_container_add(GTK_CONTAINER(window), draw_area); + GdkVisual* visual = gdk_screen_get_system_visual(gdk_screen_get_default()); + + GdkDisplay* gdk_display = gtk_widget_get_display(window); + Display* display = gdk_x11_display_get_xdisplay(gdk_display); + disp_ = display; + ::Window root = gdk_x11_get_default_root_xwindow(); + static int vis_attrib_list[] = + {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None}; + XVisualInfo* vi = glXChooseVisual(display, 0, vis_attrib_list); + if (vi == NULL) { + FatalGLError("No matching visuals for X display"); + return false; + } + + cmap_ = XCreateColormap(display, root, vi->visual, AllocNone); + + ::GLXContext temp_context = glXCreateContext(display, vi, NULL, GL_TRUE); + if (!temp_context) { + FatalGLError("Unable to create temporary GLX context"); + return false; + } + xid_ = GDK_WINDOW_XID(gtk_widget_get_window(window)); + glXMakeCurrent(display, xid_, temp_context); + + tls_glew_context_ = glew_context_.get(); + tls_glxew_context_ = glxew_context_.get(); + if (glewInit() != GLEW_OK) { + FatalGLError("Unable to initialize GLEW."); + return false; + } + if (glxewInit() != GLEW_OK) { + FatalGLError("Unable to initialize GLXEW."); + return false; + } + + if (!GLXEW_ARB_create_context) { + FatalGLError("GLX_ARB_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 |= GLX_CONTEXT_DEBUG_BIT_ARB; + } + if (robust_access_supported_) { + context_flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; + } + + int attrib_list[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, + 4, + GLX_CONTEXT_MINOR_VERSION_ARB, + 5, + GLX_CONTEXT_FLAGS_ARB, + context_flags, + GLX_CONTEXT_PROFILE_MASK_ARB, + GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + robust_access_supported_ ? GLX_LOSE_CONTEXT_ON_RESET_ARB : 0, + 0}; + GLXContext* share_context_glx = dynamic_cast(share_context); + glx_context_ = glXCreateContextAttribsARB( + display, nullptr, + share_context ? share_context_glx->glx_context_ : nullptr, True, + attrib_list); + glXMakeCurrent(display, 0, nullptr); + glXDestroyContext(display, temp_context); + if (!glx_context_) { + 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 GLXContext::CreateOffscreen( + GraphicsProvider* provider, GLXContext* parent_context) { + assert_not_null(parent_context->glx_context_); + + ::GLXContext new_glrc; + { + GraphicsContextLock context_lock(parent_context); + + int context_flags = 0; + if (FLAGS_gl_debug) { + context_flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + } + + bool robust_access_supported = parent_context->robust_access_supported_; + if (robust_access_supported) { + context_flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; + } + + int attrib_list[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, + 4, + GLX_CONTEXT_MINOR_VERSION_ARB, + 5, + GLX_CONTEXT_FLAGS_ARB, + context_flags, + GLX_CONTEXT_PROFILE_MASK_ARB, + GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, + GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, + robust_access_supported ? GLX_LOSE_CONTEXT_ON_RESET_ARB : 0, + 0}; + new_glrc = glXCreateContextAttribsARB(parent_context->disp_, nullptr, + parent_context->glx_context_, True, attrib_list); + if (!new_glrc) { + FatalGLError("Could not create shared context."); + return nullptr; + } + } + + auto new_context = std::unique_ptr( + new GLXContext(provider, parent_context->target_window_)); + new_context->glx_context_ = new_glrc; + new_context->window_ = parent_context->window_; + new_context->draw_area_ = parent_context->draw_area_; + new_context->disp_ = parent_context->disp_; + new_context->xid_ = parent_context->xid_; + 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 (glxewInit() != GLEW_OK) { + new_context->ClearCurrent(); + FatalGLError("Unable to initialize GLXEW 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; +} + + + +bool GLContext::is_current() { + return tls_glew_context_ == glew_context_.get(); +} + + +bool GLXContext::MakeCurrent() { + SCOPE_profile_cpu_f("gpu"); + if (FLAGS_thread_safe_gl) { + global_gl_mutex_.lock(); + } + + if (!glXMakeCurrent(disp_, xid_, glx_context_)) { + 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_glxew_context_ = glxew_context_.get(); + return true; +} + +void GLXContext::ClearCurrent() { + if (!FLAGS_disable_gl_context_reset) { + glXMakeCurrent(disp_, 0, nullptr); + } + tls_glew_context_ = nullptr; + tls_glxew_context_ = nullptr; + + if (FLAGS_thread_safe_gl) { + global_gl_mutex_.unlock(); + } +} + + +void GLXContext::BeginSwap() { + SCOPE_profile_cpu_i("gpu", "xe::ui::gl::GLXContext::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 GLXContext::EndSwap() { + SCOPE_profile_cpu_i("gpu", "xe::ui::gl::GLXContext::EndSwap"); + glXSwapBuffers(disp_, _xid); +} + +} // namespace gl +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/gl/gl_context_x11.h b/src/xenia/ui/gl/gl_context_x11.h new file mode 100644 index 000000000..ff61e1367 --- /dev/null +++ b/src/xenia/ui/gl/gl_context_x11.h @@ -0,0 +1,71 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2014 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_GL_GLX_CONTEXT_H_ +#define XENIA_UI_GL_GLX_CONTEXT_H_ + +#include + +#include + +#include "xenia/ui/gl/gl_context.h" +#include "xenia/ui/gl/blitter.h" +#include "xenia/ui/gl/gl.h" +#include "xenia/ui/graphics_context.h" +#include "third_party/GL/glxew.h" +#include "xenia/base/platform_linux.h" + +DECLARE_bool(thread_safe_gl); + + +namespace xe { +namespace ui { +namespace gl { + +class GLImmediateDrawer; +class GLProvider; + +class GLXContext : public GLContext { + public: + ~GLXContext() override; + + + bool is_current() override; + bool MakeCurrent() override; + void ClearCurrent() override; + + void BeginSwap() override; + void EndSwap() override; + + + protected: + static std::unique_ptr CreateOffscreen(GraphicsProvider* provider, + GLXContext* parent_context); + + bool Initialize(GLContext* share_context) override; + void* handle() override {return glx_context_;} + + private: + friend class GLContext; + GLXContext(GraphicsProvider* provider, Window* target_window); + std::unique_ptr glew_context_; + std::unique_ptr glxew_context_; + ::GLXContext glx_context_; + GtkWidget* window_; + GtkWidget* draw_area_; + Colormap cmap_; + Display* disp_; + int xid_; +}; + +} // namespace gl +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_GL_GL_CONTEXT_H_ From a9e5d7a496be5d864a07cfaa32f3bb557e0f1f60 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:33:33 -0600 Subject: [PATCH 05/38] Add GLX context for linux platform --- src/xenia/ui/gl/gl_context.h | 10 +++++----- src/xenia/ui/gl/gl_context_x11.cc | 14 +++++--------- src/xenia/ui/gl/gl_context_x11.h | 1 + 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/xenia/ui/gl/gl_context.h b/src/xenia/ui/gl/gl_context.h index b0cb3a1be..8e49b80df 100644 --- a/src/xenia/ui/gl/gl_context.h +++ b/src/xenia/ui/gl/gl_context.h @@ -43,13 +43,13 @@ class GLContext : public GraphicsContext { ImmediateDrawer* immediate_drawer() override; - bool is_current() = 0; - bool MakeCurrent() = 0; - void ClearCurrent() = 0; + virtual bool is_current() override = 0; + virtual bool MakeCurrent() override = 0; + virtual void ClearCurrent() override = 0; bool WasLost() override; - void BeginSwap() = 0; - void EndSwap() = 0; + virtual void BeginSwap() override = 0; + virtual void EndSwap() override = 0; std::unique_ptr Capture() override; Blitter* blitter() { return &blitter_; } diff --git a/src/xenia/ui/gl/gl_context_x11.cc b/src/xenia/ui/gl/gl_context_x11.cc index 5c582b92d..bc35685da 100644 --- a/src/xenia/ui/gl/gl_context_x11.cc +++ b/src/xenia/ui/gl/gl_context_x11.cc @@ -29,10 +29,6 @@ namespace ui { namespace gl { -DEFINE_bool(disable_gl_context_reset, false, - "Do not aggressively reset the GL context (helps with capture " - "programs such as OBS or FRAPS)."); -DEFINE_bool(gl_debug, false, "Enable OpenGL debug validation layer."); thread_local GLEWContext* tls_glew_context_ = nullptr; thread_local GLXEWContext* tls_glxew_context_ = nullptr; @@ -40,6 +36,7 @@ extern "C" GLEWContext* glewGetContext() { return tls_glew_context_; } extern "C" GLXEWContext* glxewGetContext() { return tls_glxew_context_; } + std::unique_ptr GLContext::Create(GraphicsProvider* provider, Window* target_window, GLContext* share_context) { @@ -52,11 +49,10 @@ std::unique_ptr GLContext::Create(GraphicsProvider* provider, return context; } - std::unique_ptr GLContext::CreateOffscreen( GraphicsProvider* provider, GLContext* parent_context) { return GLXContext::CreateOffscreen(provider, - dynamic_cast(parent_context)); + static_cast(parent_context)); } GLXContext::GLXContext(GraphicsProvider* provider, Window* target_window) @@ -152,7 +148,7 @@ bool GLXContext::Initialize(GLContext* share_context) { GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, robust_access_supported_ ? GLX_LOSE_CONTEXT_ON_RESET_ARB : 0, 0}; - GLXContext* share_context_glx = dynamic_cast(share_context); + GLXContext* share_context_glx = static_cast(share_context); glx_context_ = glXCreateContextAttribsARB( display, nullptr, share_context ? share_context_glx->glx_context_ : nullptr, True, @@ -277,7 +273,7 @@ std::unique_ptr GLXContext::CreateOffscreen( -bool GLContext::is_current() { +bool GLXContext::is_current() { return tls_glew_context_ == glew_context_.get(); } @@ -328,7 +324,7 @@ void GLXContext::BeginSwap() { void GLXContext::EndSwap() { SCOPE_profile_cpu_i("gpu", "xe::ui::gl::GLXContext::EndSwap"); - glXSwapBuffers(disp_, _xid); + glXSwapBuffers(disp_, xid_); } } // namespace gl diff --git a/src/xenia/ui/gl/gl_context_x11.h b/src/xenia/ui/gl/gl_context_x11.h index ff61e1367..789df284f 100644 --- a/src/xenia/ui/gl/gl_context_x11.h +++ b/src/xenia/ui/gl/gl_context_x11.h @@ -37,6 +37,7 @@ class GLXContext : public GLContext { bool is_current() override; + bool MakeCurrent() override; void ClearCurrent() override; From 417eacb48cfe69ff4cf18d38d0159952fe8409ce Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:35:44 -0600 Subject: [PATCH 06/38] xenia: ui: Add GTK implemention of UI --- src/xenia/ui/file_picker_gtk.cc | 75 ++++++ src/xenia/ui/loop_gtk.cc | 87 ++++++ src/xenia/ui/loop_gtk.h | 52 ++++ src/xenia/ui/window_gtk.cc | 456 ++++++++++++++++++++++++++++++++ src/xenia/ui/window_gtk.h | 103 ++++++++ 5 files changed, 773 insertions(+) create mode 100644 src/xenia/ui/file_picker_gtk.cc create mode 100644 src/xenia/ui/loop_gtk.cc create mode 100644 src/xenia/ui/loop_gtk.h create mode 100644 src/xenia/ui/window_gtk.cc create mode 100644 src/xenia/ui/window_gtk.h diff --git a/src/xenia/ui/file_picker_gtk.cc b/src/xenia/ui/file_picker_gtk.cc new file mode 100644 index 000000000..8dc52eadc --- /dev/null +++ b/src/xenia/ui/file_picker_gtk.cc @@ -0,0 +1,75 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/file_picker.h" + +#include "xenia/base/assert.h" +#include "xenia/base/platform_linux.h" +#include +#include +#include + +namespace xe { +namespace ui { + +class GtkFilePicker : public FilePicker { + public: + GtkFilePicker(); + ~GtkFilePicker() override; + + bool Show(void* parent_window_handle) override; + + private: +}; + +std::unique_ptr FilePicker::Create() { + return std::make_unique(); +} + +GtkFilePicker::GtkFilePicker() = default; + +GtkFilePicker::~GtkFilePicker() = default; + + +bool GtkFilePicker::Show(void* parent_window_handle) { + // TODO(benvanik): FileSaveDialog. + assert_true(mode() == Mode::kOpen); + // TODO(benvanik): folder dialogs. + assert_true(type() == Type::kFile); + GtkWidget *dialog; + gint res; + + dialog = gtk_file_chooser_dialog_new ("Open File", + (GtkWindow*)parent_window_handle, + GTK_FILE_CHOOSER_ACTION_OPEN, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Open", + GTK_RESPONSE_ACCEPT, + NULL); + + res = gtk_dialog_run (GTK_DIALOG (dialog)); + char *filename; + if (res == GTK_RESPONSE_ACCEPT) { + GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog); + filename = gtk_file_chooser_get_filename (chooser); + std::vector selected_files; + std::wstring_convert> converter; + std::wstring ws_filename = converter.from_bytes(filename); + selected_files.push_back(ws_filename); + set_selected_files(selected_files); + gtk_widget_destroy (dialog); + return true; + } + gtk_widget_destroy (dialog); + return false;; +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/loop_gtk.cc b/src/xenia/ui/loop_gtk.cc new file mode 100644 index 000000000..44bf1c7e4 --- /dev/null +++ b/src/xenia/ui/loop_gtk.cc @@ -0,0 +1,87 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/loop_gtk.h" + +#include "xenia/base/assert.h" + +namespace xe { +namespace ui { + + +class PostedFn { + public: + explicit PostedFn(std::function fn) : fn_(std::move(fn)) {} + void Call() { fn_(); } + + private: + std::function fn_; +}; + +std::unique_ptr Loop::Create() { return std::make_unique(); } + +GTKLoop::GTKLoop() : thread_id_(0) { + gtk_init(nullptr, nullptr); + xe::threading::Fence init_fence; + thread_ = std::thread([&init_fence, this]() { + xe::threading::set_name("GTK Loop"); + + thread_id_ = std::this_thread::get_id(); + init_fence.Signal(); + + ThreadMain(); + + quit_fence_.Signal(); + }); + init_fence.Wait(); +} + +GTKLoop::~GTKLoop() { + Quit(); + thread_.join(); +} + +void GTKLoop::ThreadMain() { + + gtk_main(); + +} + +bool GTKLoop::is_on_loop_thread() { + return thread_id_ == std::this_thread::get_id(); +} + + +gboolean _posted_fn_thunk(gpointer posted_fn) { + PostedFn* Fn = reinterpret_cast(posted_fn); + Fn->Call(); + return G_SOURCE_REMOVE; +} + +void GTKLoop::Post(std::function fn) { + assert_true(thread_id_ != std::thread::id(0)); + gdk_threads_add_idle(_posted_fn_thunk, + reinterpret_cast(new PostedFn(std::move(fn)))); +} + + +void GTKLoop::PostDelayed(std::function fn, uint64_t delay_millis) { + gdk_threads_add_timeout(delay_millis, _posted_fn_thunk, + reinterpret_cast(new PostedFn(std::move(fn)))); +} + +void GTKLoop::Quit() { + assert_true(thread_id_ != std::thread::id(0)); + +} + +void GTKLoop::AwaitQuit() { quit_fence_.Wait(); } + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/loop_gtk.h b/src/xenia/ui/loop_gtk.h new file mode 100644 index 000000000..6071851eb --- /dev/null +++ b/src/xenia/ui/loop_gtk.h @@ -0,0 +1,52 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_LOOP_GTK_H_ +#define XENIA_UI_LOOP_GTK_H_ + +#include +#include +#include + +#include "xenia/base/platform_linux.h" +#include "xenia/base/threading.h" +#include "xenia/ui/loop.h" + +namespace xe { +namespace ui { + +class GTKWindow; + +class GTKLoop : public Loop { + public: + GTKLoop(); + ~GTKLoop() override; + + bool is_on_loop_thread() override; + + void Post(std::function fn) override; + void PostDelayed(std::function fn, uint64_t delay_millis) override; + + void Quit() override; + void AwaitQuit() override; + private: + + void ThreadMain(); + + std::thread::id thread_id_; + std::thread thread_; + xe::threading::Fence quit_fence_; + + +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_LOOP_GTK_H_ diff --git a/src/xenia/ui/window_gtk.cc b/src/xenia/ui/window_gtk.cc new file mode 100644 index 000000000..fcf0f4e30 --- /dev/null +++ b/src/xenia/ui/window_gtk.cc @@ -0,0 +1,456 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include "xenia/base/assert.h" +#include "xenia/base/logging.h" +#include "xenia/base/platform_linux.h" +#include "xenia/ui/window_gtk.h" + +namespace xe { +namespace ui { + + +class FnWrapper { + public: + explicit FnWrapper(std::function fn) : fn_(std::move(fn)) {} + void Call() { fn_(); } + + private: + std::function fn_; +}; + +std::unique_ptr Window::Create(Loop* loop, const std::wstring& title) { + return std::make_unique(loop, title); +} + +GTKWindow::GTKWindow(Loop* loop, const std::wstring& title) + : Window(loop, title) {} + +GTKWindow::~GTKWindow() { + OnDestroy(); + if (window_) { + gtk_widget_destroy(window_); + window_ = nullptr; + } +} + +bool GTKWindow::Initialize() { return OnCreate(); } + +void gtk_event_handler_(GtkWidget* widget, GdkEvent* event, gpointer data) { + GTKWindow* window = reinterpret_cast(data); + switch (event->type) { + case GDK_OWNER_CHANGE: + window->HandleWindowOwnerChange(&(event->owner_change)); + break; + case GDK_VISIBILITY_NOTIFY: + window->HandleWindowVisibility(&(event->visibility)); + break; + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + window->HandleKeyboard(&(event->key)); + break; + case GDK_SCROLL: + case GDK_BUTTON_PRESS: + case GDK_MOTION_NOTIFY: + window->HandleMouse(&(event->any)); + break; + case GDK_FOCUS_CHANGE: + window->HandleWindowFocus(&(event->focus_change)); + break; + case GDK_CONFIGURE: + window->HandleWindowResize(&(event->configure)); + default: + // Do nothing + return; + } +} + +void GTKWindow::Create() { + window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(window_), (gchar*)title_.c_str()); + gtk_window_set_default_size(GTK_WINDOW(window_), 1280, 720); + gtk_widget_show_all(window_); + g_signal_connect(G_OBJECT(window_), "destroy", G_CALLBACK(gtk_main_quit), + NULL); + g_signal_connect(G_OBJECT(window_), "event", G_CALLBACK(gtk_event_handler_), + reinterpret_cast(this)); +} + +bool GTKWindow::OnCreate() { + loop()->PostSynchronous([this]() { this->Create(); }); + return super::OnCreate(); +} + +void GTKWindow::OnDestroy() { super::OnDestroy(); } + +void GTKWindow::OnClose() { + if (!closing_ && window_) { + closing_ = true; + gtk_widget_destroy(window_); + window_ = nullptr; + } + super::OnClose(); +} + +bool GTKWindow::set_title(const std::wstring& title) { + if (!super::set_title(title)) { + return false; + } + gtk_window_set_title(GTK_WINDOW(window_), (gchar*)title.c_str()); + return true; +} + +bool GTKWindow::SetIcon(const void* buffer, size_t size) { + // TODO(dougvj) Set icon after changin buffer to the correct format. (the + // call is gtk_window_set_icon) + return false; +} + +bool GTKWindow::is_fullscreen() const { return fullscreen_; } + +void GTKWindow::ToggleFullscreen(bool fullscreen) { + if (fullscreen == is_fullscreen()) { + return; + } + + fullscreen_ = fullscreen; + + if (fullscreen) { + gtk_window_fullscreen(GTK_WINDOW(window_)); + } else { + gtk_window_unfullscreen(GTK_WINDOW(window_)); + } +} + +bool GTKWindow::is_bordered() const { + return gtk_window_get_decorated(GTK_WINDOW(window_)); +} + +void GTKWindow::set_bordered(bool enabled) { + if (is_fullscreen()) { + // Don't screw with the borders if we're fullscreen. + return; + } + + gtk_window_set_decorated(GTK_WINDOW(window_), enabled); +} + +void GTKWindow::set_cursor_visible(bool value) { + if (is_cursor_visible_ == value) { + return; + } + if (value) { + // TODO(dougvj) Show and hide cursor + } else { + } +} + +void GTKWindow::set_focus(bool value) { + if (has_focus_ == value) { + return; + } + if (window_) { + if (value) { + gtk_window_activate_focus(GTK_WINDOW(window_)); + } else { + // TODO(dougvj) Check to see if we need to do somethign here to unset + // the focus. + } + } else { + has_focus_ = value; + } +} + +void GTKWindow::Resize(int32_t width, int32_t height) { + gtk_window_resize(GTK_WINDOW(window_), width, height); +} + +void GTKWindow::Resize(int32_t left, int32_t top, int32_t right, + int32_t bottom) { + // TODO(dougvj) Verify that this is the desired behavior from this call + gtk_window_move(GTK_WINDOW(window_), left, top); + gtk_window_resize(GTK_WINDOW(window_), left - right, top - bottom); +} + +void GTKWindow::OnResize(UIEvent* e) { + int32_t width; + int32_t height; + gtk_window_get_size(GTK_WINDOW(window_), &width, &height); + if (width != width_ || height != height_) { + width_ = width; + height_ = height; + Layout(); + } + super::OnResize(e); +} + +void GTKWindow::Invalidate() { + super::Invalidate(); + // TODO(dougvj) I am not sure what this is supposed to do +} + +void GTKWindow::Close() { + if (closing_) { + return; + } + closing_ = true; + Close(); + OnClose(); +} + +void GTKWindow::OnMainMenuChange() { + // We need to store the old handle for detachment + static GtkWidget* box = nullptr; + auto main_menu = reinterpret_cast(main_menu_.get()); + if (main_menu && !is_fullscreen()) { + if (box) gtk_widget_destroy(box); + GtkWidget* menu = main_menu->handle(); + box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5); + gtk_box_pack_start(GTK_BOX(box), menu, FALSE, FALSE, 3); + gtk_container_add(GTK_CONTAINER(window_), box); + } +} + + + +bool GTKWindow::HandleWindowOwnerChange(GdkEventOwnerChange* event) { + if (event->type == GDK_OWNER_CHANGE) { + if (event->reason == GDK_OWNER_CHANGE_DESTROY) { + OnDestroy(); + } else if (event->reason == GDK_OWNER_CHANGE_CLOSE) { + closing_ = true; + Close(); + OnClose(); + } + return true; + } + return false; +} + +bool GTKWindow::HandleWindowResize(GdkEventConfigure* event) { + if (event->type == GDK_CONFIGURE) { + auto e = UIEvent(this); + OnResize(&e); + return true; + } + return false; +} + + + +bool GTKWindow::HandleWindowVisibility(GdkEventVisibility* event) { + // TODO(dougvj) The gdk docs say that this is deprecated because modern window + // managers composite everything and nothing is truly hidden. + if (event->type == GDK_VISIBILITY_NOTIFY) { + if (event->state == GDK_VISIBILITY_UNOBSCURED) { + auto e = UIEvent(this); + OnVisible(&e); + } else { + auto e = UIEvent(this); + OnHidden(&e); + } + return true; + } + return false; +} + +bool GTKWindow::HandleWindowFocus(GdkEventFocus* event) { + if (event->type == GDK_FOCUS_CHANGE) { + if (!event->in) { + has_focus_ = false; + auto e = UIEvent(this); + OnLostFocus(&e); + } else { + has_focus_ = true; + auto e = UIEvent(this); + OnGotFocus(&e); + } + return true; + } + return false; +} + +bool GTKWindow::HandleMouse(GdkEventAny* event) { + MouseEvent::Button button = MouseEvent::Button::kNone; + int32_t dx = 0; + int32_t dy = 0; + int32_t x = 0; + int32_t y = 0; + switch (event->type) { + default: + // Double click/etc? + return true; + case GDK_BUTTON_PRESS: + case GDK_BUTTON_RELEASE: { + GdkEventButton* e = reinterpret_cast(event); + switch (e->button) { + case 1: + button = MouseEvent::Button::kLeft; + break; + case 3: + button = MouseEvent::Button::kRight; + break; + case 2: + button = MouseEvent::Button::kMiddle; + break; + case 4: + button = MouseEvent::Button::kX1; + break; + case 5: + button = MouseEvent::Button::kX2; + break; + } + x = e->x; + y = e->y; + break; + } + case GDK_MOTION_NOTIFY: { + GdkEventMotion* e = reinterpret_cast(event); + x = e->x; + y = e->y; + break; + } + case GDK_SCROLL: { + GdkEventScroll* e = reinterpret_cast(event); + x = e->x; + y = e->y; + dx = e->delta_x; + dy = e->delta_y; + break; + } + } + + auto e = MouseEvent(this, button, x, y, dx, dy); + switch (event->type) { + case GDK_BUTTON_PRESS: + OnMouseDown(&e); + break; + case GDK_BUTTON_RELEASE: + OnMouseUp(&e); + break; + case GDK_MOTION_NOTIFY: + OnMouseMove(&e); + break; + case GDK_SCROLL: + OnMouseWheel(&e); + break; + default: + return false; + } + return e.is_handled(); +} + +bool GTKWindow::HandleKeyboard(GdkEventKey* event) { + unsigned int modifiers = event->state; + bool shift_pressed = modifiers & GDK_SHIFT_MASK; + bool ctrl_pressed = modifiers & GDK_CONTROL_MASK; + bool alt_pressed = modifiers & GDK_META_MASK; + bool super_pressed = modifiers & GDK_SUPER_MASK; + auto e = + KeyEvent(this, event->hardware_keycode, 1, event->type == GDK_KEY_RELEASE, + shift_pressed, ctrl_pressed, alt_pressed, super_pressed); + switch (event->type) { + case GDK_KEY_PRESS: + OnKeyDown(&e); + break; + case GDK_KEY_RELEASE: + OnKeyUp(&e); + break; +// TODO(dougvj) GDK doesn't have a KEY CHAR event, so we will have to +// figure out its equivalent here to call OnKeyChar(&e); + default: + return false; + } + return e.is_handled(); +} + +std::unique_ptr MenuItem::Create(Type type, + const std::wstring& text, + const std::wstring& hotkey, + std::function callback) { + return std::make_unique(type, text, hotkey, callback); +} + +static void _menu_activate_callback(GtkWidget* menu, gpointer data) { + auto fn = reinterpret_cast(data); + fn->Call(); + delete fn; +} + +GTKMenuItem::GTKMenuItem(Type type, const std::wstring& text, + const std::wstring& hotkey, + std::function callback) + : MenuItem(type, text, hotkey, std::move(callback)) { + switch (type) { + case MenuItem::Type::kNormal: + default: + menu_ = gtk_menu_bar_new(); + break; + case MenuItem::Type::kPopup: + menu_ = gtk_menu_item_new_with_label((gchar*)xe::to_string(text).c_str()); + break; + case MenuItem::Type::kSeparator: + menu_ = gtk_separator_menu_item_new(); + break; + case MenuItem::Type::kString: + auto full_name = text; + if (!hotkey.empty()) { + full_name += L"\t" + hotkey; + } + menu_ = gtk_menu_item_new_with_label( + (gchar*)xe::to_string(full_name).c_str()); + break; + } + if (GTK_IS_MENU_ITEM(menu_)) + g_signal_connect(menu_, "activate", G_CALLBACK(_menu_activate_callback), + (gpointer) new FnWrapper(callback)); +} + +GTKMenuItem::~GTKMenuItem() { + if (menu_) { + } +} + +void GTKMenuItem::OnChildAdded(MenuItem* generic_child_item) { + auto child_item = static_cast(generic_child_item); + switch (child_item->type()) { + case MenuItem::Type::kNormal: + // Nothing special. + break; + case MenuItem::Type::kPopup: + if (GTK_IS_MENU_ITEM(menu_)) { + assert(gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_)) == nullptr); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_), child_item->handle()); + } else { + gtk_menu_shell_append(GTK_MENU_SHELL(menu_), child_item->handle()); + } + break; + case MenuItem::Type::kSeparator: + case MenuItem::Type::kString: + assert(GTK_IS_MENU_ITEM(menu_)); + // Get sub menu and if it doesn't exist create it + GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_)); + if (submenu == nullptr) { + submenu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_), submenu); + } + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), child_item->handle()); + break; + } +} + +// TODO(dougvj) +void GTKMenuItem::OnChildRemoved(MenuItem* generic_child_item) { + assert_always(); +} + +} // namespace ui +} // namespace xe diff --git a/src/xenia/ui/window_gtk.h b/src/xenia/ui/window_gtk.h new file mode 100644 index 000000000..f6e18753f --- /dev/null +++ b/src/xenia/ui/window_gtk.h @@ -0,0 +1,103 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_WINDOW_GTK_H_ +#define XENIA_UI_WINDOW_GTK_H_ + +#include +#include + +#include "xenia/ui/menu_item.h" +#include "xenia/ui/window.h" +#include "xenia/base/platform_linux.h" + +namespace xe { +namespace ui { + +class GTKWindow : public Window { + using super = Window; + + public: + GTKWindow(Loop* loop, const std::wstring& title); + ~GTKWindow() override; + + NativePlatformHandle native_platform_handle() const override {return nullptr;} + NativeWindowHandle native_handle() const override { return window_;} + + + bool set_title(const std::wstring& title) override; + + bool SetIcon(const void* buffer, size_t size) override; + + bool is_fullscreen() const override; + void ToggleFullscreen(bool fullscreen) override; + + bool is_bordered() const override; + void set_bordered(bool enabled) override; + + void set_cursor_visible(bool value) override; + void set_focus(bool value) override; + + void Resize(int32_t width, int32_t height) override; + void Resize(int32_t left, int32_t top, int32_t right, + int32_t bottom) override; + + bool Initialize() override; + void Invalidate() override; + void Close() override; + + protected: + bool OnCreate() override; + void OnMainMenuChange() override; + void OnDestroy() override; + void OnClose() override; + + void OnResize(UIEvent* e) override; + + + private: + void Create(); + GtkWidget* window_; + + friend void gtk_event_handler_(GtkWidget*, GdkEvent*, gpointer); + bool HandleMouse(GdkEventAny* event); + bool HandleKeyboard(GdkEventKey* event); + bool HandleWindowResize(GdkEventConfigure* event); + bool HandleWindowFocus(GdkEventFocus* event); + bool HandleWindowVisibility(GdkEventVisibility* event); + bool HandleWindowOwnerChange(GdkEventOwnerChange* event); + + bool closing_ = false; + bool fullscreen_ = false; + +}; + +class GTKMenuItem : public MenuItem { + public: + GTKMenuItem(Type type, const std::wstring& text, const std::wstring& hotkey, + std::function callback); + ~GTKMenuItem() override; + + GtkWidget* handle() {return menu_;} + using MenuItem::OnSelected; + + protected: + void OnChildAdded(MenuItem* child_item) override; + void OnChildRemoved(MenuItem* child_item) override; + GTKMenuItem* parent_ = nullptr; + GTKMenuItem* child_ = nullptr; + + private: + GtkWidget* menu_ = nullptr; +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_WINDOW_WIN_H_ From 48a2435bdee693ec9a063322916271c768d3d7a4 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:40:30 -0600 Subject: [PATCH 07/38] Add header dependencies that prevented linux build There were several files with dependancies on vector and cmath that caused compiler errors under linux. In addition, there was a printf formatting error that threw a compiler error as well --- src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc | 1 + src/xenia/cpu/compiler/passes/value_reduction_pass.cc | 1 + src/xenia/gpu/command_processor.h | 1 + src/xenia/gpu/gl4/gl4_shader_cache.cc | 2 +- src/xenia/gpu/gl4/gl4_shader_cache.h | 4 +++- 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc b/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc index a858e4329..5f403c738 100644 --- a/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc +++ b/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc @@ -23,6 +23,7 @@ #include #pragma warning(pop) #else +#include #include #endif // XE_COMPILER_MSVC diff --git a/src/xenia/cpu/compiler/passes/value_reduction_pass.cc b/src/xenia/cpu/compiler/passes/value_reduction_pass.cc index 94a218219..635290d67 100644 --- a/src/xenia/cpu/compiler/passes/value_reduction_pass.cc +++ b/src/xenia/cpu/compiler/passes/value_reduction_pass.cc @@ -22,6 +22,7 @@ #include #pragma warning(pop) #else +#include #include #endif // XE_COMPILER_MSVC diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h index a418dd683..e8f7fffec 100644 --- a/src/xenia/gpu/command_processor.h +++ b/src/xenia/gpu/command_processor.h @@ -240,3 +240,4 @@ class CommandProcessor { } // namespace xe #endif // XENIA_GPU_COMMAND_PROCESSOR_H_ + diff --git a/src/xenia/gpu/gl4/gl4_shader_cache.cc b/src/xenia/gpu/gl4/gl4_shader_cache.cc index 033ed1b5e..714de3e1d 100644 --- a/src/xenia/gpu/gl4/gl4_shader_cache.cc +++ b/src/xenia/gpu/gl4/gl4_shader_cache.cc @@ -184,4 +184,4 @@ GL4Shader* GL4ShaderCache::FindCachedShader(ShaderType shader_type, } // namespace gl4 } // namespace gpu -} // namespace xe \ No newline at end of file +} // namespace xe diff --git a/src/xenia/gpu/gl4/gl4_shader_cache.h b/src/xenia/gpu/gl4/gl4_shader_cache.h index 7bac4c084..59eaf665e 100644 --- a/src/xenia/gpu/gl4/gl4_shader_cache.h +++ b/src/xenia/gpu/gl4/gl4_shader_cache.h @@ -11,6 +11,8 @@ #define XENIA_GPU_GL4_SHADER_CACHE_H_ #include +#include +#include #include #include @@ -57,4 +59,4 @@ class GL4ShaderCache { } // namespace gpu } // namespace xe -#endif // XENIA_GPU_GL4_SHADER_CACHE_H_ \ No newline at end of file +#endif // XENIA_GPU_GL4_SHADER_CACHE_H_ From 41dafa88609ef07f0b42f00b23406a86c071939e Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:43:19 -0600 Subject: [PATCH 08/38] Add stub exception handler backend for linux --- src/xenia/base/exception_handler_linux.cc | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/xenia/base/exception_handler_linux.cc diff --git a/src/xenia/base/exception_handler_linux.cc b/src/xenia/base/exception_handler_linux.cc new file mode 100644 index 000000000..16fc669ad --- /dev/null +++ b/src/xenia/base/exception_handler_linux.cc @@ -0,0 +1,36 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2015 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/exception_handler.h" + +#include "xenia/base/assert.h" +#include "xenia/base/math.h" +#include "xenia/base/platform_linux.h" + +namespace xe { + +// This can be as large as needed, but isn't often needed. +// As we will be sometimes firing many exceptions we want to avoid having to +// scan the table too much or invoke many custom handlers. +constexpr size_t kMaxHandlerCount = 8; + +// All custom handlers, left-aligned and null terminated. +// Executed in order. +std::pair handlers_[kMaxHandlerCount]; + + +void ExceptionHandler::Install(Handler fn, void* data) { + //TODO(dougvj) stub +} + +void ExceptionHandler::Uninstall(Handler fn, void* data) { + //TODO(dougvj) stub +} + +} // namespace xe From 2dbdc24d52df0fcc1587cf710dade3751cbf9219 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:43:59 -0600 Subject: [PATCH 09/38] Add LaunchBrowser implementation for linux --- src/xenia/base/math.h | 2 +- src/xenia/base/platform_linux.cc | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/xenia/base/platform_linux.cc diff --git a/src/xenia/base/math.h b/src/xenia/base/math.h index 539a98b3c..2e87d87d5 100644 --- a/src/xenia/base/math.h +++ b/src/xenia/base/math.h @@ -14,7 +14,7 @@ #include #include #include - +#include #include "xenia/base/platform.h" #if XE_ARCH_AMD64 diff --git a/src/xenia/base/platform_linux.cc b/src/xenia/base/platform_linux.cc new file mode 100644 index 000000000..053cbd7c4 --- /dev/null +++ b/src/xenia/base/platform_linux.cc @@ -0,0 +1,22 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2015 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/base/platform_linux.h" +#include +#include + +namespace xe { + +void LaunchBrowser(const char* url) { + auto cmd = std::string("xdg-open " + std::string(url)); + system(cmd.c_str()); +} + + +} // namespace xe From f8093cb1e04a4ae78ed2a358ec2e7b403ae2bcda Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:45:06 -0600 Subject: [PATCH 10/38] Add gtk and x11 headers to linux specific platform header --- src/xenia/base/platform_linux.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/xenia/base/platform_linux.h diff --git a/src/xenia/base/platform_linux.h b/src/xenia/base/platform_linux.h new file mode 100644 index 000000000..dd2ecb66d --- /dev/null +++ b/src/xenia/base/platform_linux.h @@ -0,0 +1,30 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2015 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_BASE_PLATFORM_X11_H_ +#define XENIA_BASE_PLATFORM_X11_H_ + +// NOTE: if you're including this file it means you are explicitly depending +// on Linux headers. Including this file outside of linux platform specific +// source code will break portability + +#include "xenia/base/platform.h" + +// Xlib is used only for GLX interaction, the window management and input +// events are done with gtk/gdk +#include +#include +#include + +//Used for window management. Gtk is for GUI and wigets, gdk is for lower +//level events like key presses, mouse events, etc +#include +#include + +#endif // XENIA_BASE_PLATFORM_X11_H_ From 4abb1623eab78e920bc3bb00ab5be61745f80b97 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:46:48 -0600 Subject: [PATCH 11/38] Add _gtk and _x11 as linux specific platform files --- tools/build/scripts/platform_files.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/build/scripts/platform_files.lua b/tools/build/scripts/platform_files.lua index b6d2e9ecc..4c887115e 100644 --- a/tools/build/scripts/platform_files.lua +++ b/tools/build/scripts/platform_files.lua @@ -13,6 +13,8 @@ local function match_platform_files(base_path, base_match) removefiles({base_path.."/".."**_test.cc"}) removefiles({base_path.."/".."**_posix.h", base_path.."/".."**_posix.cc"}) removefiles({base_path.."/".."**_linux.h", base_path.."/".."**_linux.cc"}) + removefiles({base_path.."/".."**_x11.h", base_path.."/".."**_x11.cc"}) + removefiles({base_path.."/".."**_gtk.h", base_path.."/".."**_gtk.cc"}) removefiles({base_path.."/".."**_mac.h", base_path.."/".."**_mac.cc"}) removefiles({base_path.."/".."**_win.h", base_path.."/".."**_win.cc"}) filter("platforms:Windows") @@ -26,6 +28,10 @@ local function match_platform_files(base_path, base_match) base_path.."/"..base_match.."_posix.cc", base_path.."/"..base_match.."_linux.h", base_path.."/"..base_match.."_linux.cc", + base_path.."/"..base_match.."_x11.h", + base_path.."/"..base_match.."_x11.cc", + base_path.."/"..base_match.."_gtk.h", + base_path.."/"..base_match.."_gtk.cc", }) filter({}) end From 1dc346d0dfad6b534d1c47e0248017332d6b32af Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 09:06:36 -0600 Subject: [PATCH 12/38] Add additional build instructions for Linux --- docs/building.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/building.md b/docs/building.md index 5a0a725d9..6e324711c 100644 --- a/docs/building.md +++ b/docs/building.md @@ -52,6 +52,14 @@ sudo -E apt-get -yq update &>> ~/apt-get-update.log sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install clang-3.8 clang-format-3.8 ``` +You will also need some development libraries. To get them on an ubuntu system: +``` +sudo apt-get install libgtk-3-dev libpthread-stubs0-dev liblz4-dev libglew-dev libx11-dev +``` + +In addition, you will need the latest OpenGL libraries and drivers for your hardware. Intel and the open source +drivers are not supported as they do not yet support OpenGL 4.5. + ## Running To make life easier you can use `--flagfile=myflags.txt` to specify all From 91cfd7f7845043691a29c542de7465fde3c95491 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 01:45:17 -0600 Subject: [PATCH 13/38] Add missing include of --- src/xenia/base/threading.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xenia/base/threading.h b/src/xenia/base/threading.h index 62fb5e815..bb447f282 100644 --- a/src/xenia/base/threading.h +++ b/src/xenia/base/threading.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace xe { namespace threading { From 9275f152795797f6612031c946db0a621780a2b8 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 01:45:56 -0600 Subject: [PATCH 14/38] Add missing consts for default vulkan config dirs on linux --- third_party/vulkan/loader/premake5.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/third_party/vulkan/loader/premake5.lua b/third_party/vulkan/loader/premake5.lua index 15d05f44c..ea6fbebf7 100644 --- a/third_party/vulkan/loader/premake5.lua +++ b/third_party/vulkan/loader/premake5.lua @@ -31,5 +31,7 @@ project("vulkan-loader") filter("platforms:Linux") defines({ [[SYSCONFDIR="\"/etc\""]], + [[FALLBACK_CONFIG_DIRS="\"/etc/xdg\""]], [[DATADIR="\"/usr/share\""]], + [[FALLBACK_DATA_DIRS="\"/usr/share:/usr/local/share\""]], }) From be3615b15bb03e9ce663700a1a46cf2f0c6241b8 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 02:41:29 -0600 Subject: [PATCH 15/38] Add missing include --- src/xenia/gpu/spirv_shader_translator.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index b7feb21e2..2c50f6c07 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -13,6 +13,7 @@ #include #include +#include #include "xenia/base/logging.h" #include "xenia/gpu/spirv/passes/control_flow_analysis_pass.h" From a8053f72e54e41011cad782cb37801dc26af6251 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 22:23:20 -0600 Subject: [PATCH 16/38] Add xcb headers to linux platform, needed for vulkan --- src/xenia/base/platform_linux.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/xenia/base/platform_linux.h b/src/xenia/base/platform_linux.h index dd2ecb66d..f77eb1235 100644 --- a/src/xenia/base/platform_linux.h +++ b/src/xenia/base/platform_linux.h @@ -16,11 +16,12 @@ #include "xenia/base/platform.h" -// Xlib is used only for GLX interaction, the window management and input -// events are done with gtk/gdk +// Xlib/Xcb is used only for GLX/Vulkan interaction, the window management +// and input events are done with gtk/gdk #include #include #include +#include //Used for window management. Gtk is for GUI and wigets, gdk is for lower //level events like key presses, mouse events, etc From 5d579fc8461ea0bc32ab09da690c5cdf99018219 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 03:19:32 -0600 Subject: [PATCH 17/38] Add Linux vulkan init routines using xcb lib --- src/xenia/ui/vulkan/vulkan_context.cc | 30 +++++++++++++++++++++++++- src/xenia/ui/vulkan/vulkan_instance.cc | 30 +++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/xenia/ui/vulkan/vulkan_context.cc b/src/xenia/ui/vulkan/vulkan_context.cc index 381fb0ab7..cef115278 100644 --- a/src/xenia/ui/vulkan/vulkan_context.cc +++ b/src/xenia/ui/vulkan/vulkan_context.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2017 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -25,6 +25,10 @@ #include "xenia/ui/vulkan/vulkan_util.h" #include "xenia/ui/window.h" +#if XE_PLATFORM_LINUX +#include "xenia/ui/window_gtk.h" +#endif + namespace xe { namespace ui { namespace vulkan { @@ -61,6 +65,30 @@ bool VulkanContext::Initialize() { auto err = vkCreateWin32SurfaceKHR(*provider->instance(), &create_info, nullptr, &surface); CheckResult(err, "vkCreateWin32SurfaceKHR"); +#elif XE_PLATFORM_LINUX +#ifdef GDK_WINDOWING_X11 + GtkWidget* window_handle = + static_cast(target_window_->native_handle()); + GdkDisplay* gdk_display = gtk_widget_get_display(window_handle); + assert(GDK_IS_X11_DISPLAY(gdk_display)); + xcb_connection_t* connection = + XGetXCBConnection(gdk_x11_display_get_xdisplay(gdk_display)); + xcb_window_t window = gdk_x11_window_get_xid( + gtk_widget_get_window(window_handle)); + VkXcbSurfaceCreateInfoKHR create_info; + create_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.connection = static_cast + (target_window_->native_platform_handle()); + create_info.window = + static_cast(window); + auto err = vkCreateXcbSurfaceKHR(*provider->instance(), &create_info, + nullptr, &surface); + CheckResult(err, "vkCreateXcbSurfaceKHR"); +#else +#error Unsupported GDK Backend on Linux. +#endif // GDK_WINDOWING_X11 #else #error Platform not yet implemented. #endif // XE_PLATFORM_WIN32 diff --git a/src/xenia/ui/vulkan/vulkan_instance.cc b/src/xenia/ui/vulkan/vulkan_instance.cc index cb7a3ee91..6aaa8c41c 100644 --- a/src/xenia/ui/vulkan/vulkan_instance.cc +++ b/src/xenia/ui/vulkan/vulkan_instance.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2017 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -26,6 +26,10 @@ #include "xenia/ui/vulkan/vulkan_util.h" #include "xenia/ui/window.h" +#if XE_PLATFORM_LINUX +#include "xenia/ui/window_gtk.h" +#endif + #define VK_API_VERSION VK_API_VERSION_1_0 namespace xe { @@ -385,6 +389,30 @@ bool VulkanInstance::QueryDevices(Window* any_target_window) { create_info.hwnd = static_cast(any_target_window->native_handle()); err = vkCreateWin32SurfaceKHR(handle, &create_info, nullptr, &any_surface); CheckResult(err, "vkCreateWin32SurfaceKHR"); +#elif XE_PLATFORM_LINUX +#ifdef GDK_WINDOWING_X11 + GtkWidget* window_handle = + static_cast(any_target_window->native_handle()); + GdkDisplay* gdk_display = gtk_widget_get_display(window_handle); + assert(GDK_IS_X11_DISPLAY(gdk_display)); + xcb_connection_t* connection = + XGetXCBConnection(gdk_x11_display_get_xdisplay(gdk_display)); + xcb_window_t window = gdk_x11_window_get_xid( + gtk_widget_get_window(window_handle)); + VkXcbSurfaceCreateInfoKHR create_info; + create_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; + create_info.pNext = nullptr; + create_info.flags = 0; + create_info.connection = static_cast + (any_target_window->native_platform_handle()); + create_info.window = + static_cast(window); + auto err = vkCreateXcbSurfaceKHR(handle, &create_info, + nullptr, &any_surface); + CheckResult(err, "vkCreateXcbSurfaceKHR"); +#else +#error Unsupported GDK Backend on Linux. +#endif // GDK_WINDOWING_X11 #else #error Platform not yet implemented. #endif // XE_PLATFORM_WIN32 From 30740664637ed6a301a5e8e54faed90b0ca90709 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 21:09:21 -0600 Subject: [PATCH 18/38] Add xb symlink to xenia-build to match xb.bat for win --- xb | 1 + 1 file changed, 1 insertion(+) create mode 120000 xb diff --git a/xb b/xb new file mode 120000 index 000000000..e841366c6 --- /dev/null +++ b/xb @@ -0,0 +1 @@ +xenia-build \ No newline at end of file From 71294a79b8fc61e43344e7d76c48b503311947ab Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 22:17:11 -0600 Subject: [PATCH 19/38] Add const qualifiers to SpvBuilder.h in glslang lib This was needed because the temporary vectors passed as non-const were throwing a compiler error in linux. The updated library appears to have fixed this, but there were other changes that could break compatability so these qualifiers were added manually --- third_party/glslang-spirv/SpvBuilder.cpp | 20 ++++++++++---------- third_party/glslang-spirv/SpvBuilder.h | 16 ++++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/third_party/glslang-spirv/SpvBuilder.cpp b/third_party/glslang-spirv/SpvBuilder.cpp index 13a6c946a..36bededc5 100644 --- a/third_party/glslang-spirv/SpvBuilder.cpp +++ b/third_party/glslang-spirv/SpvBuilder.cpp @@ -77,7 +77,7 @@ Id Builder::import(const char* name) { Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); import->addStringOperand(name); - + imports.push_back(std::unique_ptr(import)); return import->getResultId(); } @@ -244,7 +244,7 @@ Id Builder::makeStructResultType(Id type0, Id type1) type = groupedTypes[OpTypeStruct][t]; if (type->getNumOperands() != 2) continue; - if (type->getIdOperand(0) != type0 || + if (type->getIdOperand(0) != type0 || type->getIdOperand(1) != type1) continue; return type->getResultId(); @@ -626,7 +626,7 @@ Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, bool Builder::isConstantOpCode(Op opcode) const { switch (opcode) { - case OpUndef: + case OpUndef: case OpConstantTrue: case OpConstantFalse: case OpConstant: @@ -743,7 +743,7 @@ Id Builder::makeDoubleConstant(double d, bool specConstant) return c->getResultId(); } -Id Builder::findCompositeConstant(Op typeClass, std::vector& comps) const +Id Builder::findCompositeConstant(Op typeClass, const std::vector& comps) const { Instruction* constant = 0; bool found = false; @@ -772,7 +772,7 @@ Id Builder::findCompositeConstant(Op typeClass, std::vector& comps) const } // Comments in header -Id Builder::makeCompositeConstant(Id typeId, std::vector& members, bool specConstant) +Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, bool specConstant) { Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite; assert(typeId); @@ -1022,7 +1022,7 @@ Id Builder::createLoad(Id lValue) } // Comments in header -Id Builder::createAccessChain(StorageClass storageClass, Id base, std::vector& offsets) +Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector& offsets) { // Figure out the final resulting type. spv::Id typeId = getTypeId(base); @@ -1089,7 +1089,7 @@ Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned i return insert->getResultId(); } -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vector& indexes) +Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes) { Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); insert->addIdOperand(object); @@ -1210,7 +1210,7 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) return op->getResultId(); } -Id Builder::createFunctionCall(spv::Function* function, std::vector& args) +Id Builder::createFunctionCall(spv::Function* function, const std::vector& args) { Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); op->addIdOperand(function->getId()); @@ -1647,7 +1647,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b } // OpCompositeConstruct -Id Builder::createCompositeConstruct(Id typeId, std::vector& constituents) +Id Builder::createCompositeConstruct(Id typeId, const std::vector& constituents) { assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size())); @@ -1848,7 +1848,7 @@ void Builder::If::makeEndIf() } // Comments in header -void Builder::makeSwitch(Id selector, int numSegments, std::vector& caseValues, std::vector& valueIndexToSegment, int defaultSegment, +void Builder::makeSwitch(Id selector, int numSegments, const std::vector& caseValues, const std::vector& valueIndexToSegment, int defaultSegment, std::vector& segmentBlocks) { Function& function = buildPoint->getParent(); diff --git a/third_party/glslang-spirv/SpvBuilder.h b/third_party/glslang-spirv/SpvBuilder.h index 7eae4fe91..28f846578 100644 --- a/third_party/glslang-spirv/SpvBuilder.h +++ b/third_party/glslang-spirv/SpvBuilder.h @@ -192,7 +192,7 @@ public: Id makeDoubleConstant(double d, bool specConstant = false); // Turn the array of constants into a proper spv constant of the requested type. - Id makeCompositeConstant(Id type, std::vector& comps, bool specConst = false); + Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); // Methods for adding information outside the CFG. Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); @@ -240,7 +240,7 @@ public: Id createLoad(Id lValue); // Create an OpAccessChain instruction - Id createAccessChain(StorageClass, Id base, std::vector& offsets); + Id createAccessChain(StorageClass, Id base, const std::vector& offsets); // Create an OpArrayLength instruction Id createArrayLength(Id base, unsigned int member); @@ -249,7 +249,7 @@ public: Id createCompositeExtract(Id composite, Id typeId, unsigned index); Id createCompositeExtract(Id composite, Id typeId, std::vector& indexes); Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); - Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector& indexes); + Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); @@ -263,7 +263,7 @@ public: Id createBinOp(Op, Id typeId, Id operand1, Id operand2); Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); Id createOp(Op, Id typeId, const std::vector& operands); - Id createFunctionCall(spv::Function*, std::vector&); + Id createFunctionCall(spv::Function*, const std::vector&); // Take an rvalue (source) and a set of channels to extract from it to // make a new rvalue, which is returned. @@ -296,7 +296,7 @@ public: // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. // The type of the created vector is a vector of components of the same type as the scalar. // - // Note: One of the arguments will change, with the result coming back that way rather than + // Note: One of the arguments will change, with the result coming back that way rather than // through the return value. void promoteScalar(Decoration precision, Id& left, Id& right); @@ -341,7 +341,7 @@ public: Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); // OpCompositeConstruct - Id createCompositeConstruct(Id typeId, std::vector& constituents); + Id createCompositeConstruct(Id typeId, const std::vector& constituents); // vector or scalar constructor Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); @@ -383,7 +383,7 @@ public: // Returns the right set of basic blocks to start each code segment with, so that the caller's // recursion stack can hold the memory for it. // - void makeSwitch(Id condition, int numSegments, std::vector& caseValues, std::vector& valueToSegment, int defaultSegment, + void makeSwitch(Id condition, int numSegments, const std::vector& caseValues, const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); // return argument // Add a branch to the innermost switch's merge block. @@ -525,7 +525,7 @@ public: Id makeIntConstant(Id typeId, unsigned value, bool specConstant); Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const; Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const; - Id findCompositeConstant(Op typeClass, std::vector& comps) const; + Id findCompositeConstant(Op typeClass, const std::vector& comps) const; Id collapseAccessChain(); void transferAccessChainSwizzle(bool dynamic); void simplifyAccessChainSwizzle(); From bb0ee0e4a3067e12861f167d4a7595c6380bcb10 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 22:24:28 -0600 Subject: [PATCH 20/38] Change glsl lang call that supports scalar rather than vector --- src/xenia/gpu/spirv_shader_translator.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index 2c50f6c07..4ff803ab6 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2017 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -341,8 +341,7 @@ void SpirvShaderTranslator::StartTranslation() { registers_ptr_, std::vector({b.makeUintConstant(0)})); auto r0 = b.createLoad(r0_ptr); - r0 = b.createCompositeInsert(vertex_idx, r0, vec4_float_type_, - std::vector({0})); + r0 = b.createCompositeInsert(vertex_idx, r0, vec4_float_type_, 0); b.createStore(r0, r0_ptr); } else { // Pixel inputs from vertex shader. From 136cc92a66930ec4e2de294f34e913d291014671 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 22:27:30 -0600 Subject: [PATCH 21/38] Remove platform specific headers where unnecessary --- src/xenia/hid/hid_demo.cc | 3 +-- src/xenia/ui/window_demo.cc | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/xenia/hid/hid_demo.cc b/src/xenia/hid/hid_demo.cc index 0f11a4922..5ccf0bf75 100644 --- a/src/xenia/hid/hid_demo.cc +++ b/src/xenia/hid/hid_demo.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2015 Ben Vanik. All rights reserved. * + * Copyright 2017 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -15,7 +15,6 @@ #include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/base/main.h" -#include "xenia/base/platform_win.h" #include "xenia/base/threading.h" #include "xenia/hid/input_system.h" #include "xenia/ui/gl/gl_provider.h" diff --git a/src/xenia/ui/window_demo.cc b/src/xenia/ui/window_demo.cc index 454864a92..13b3689af 100644 --- a/src/xenia/ui/window_demo.cc +++ b/src/xenia/ui/window_demo.cc @@ -15,7 +15,6 @@ #include "xenia/base/clock.h" #include "xenia/base/logging.h" #include "xenia/base/main.h" -#include "xenia/base/platform_win.h" #include "xenia/base/profiling.h" #include "xenia/base/threading.h" #include "xenia/ui/graphics_provider.h" From 224c7795541de0406dfb239d3b8bb50ebf0701ca Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 22:30:43 -0600 Subject: [PATCH 22/38] Add missing climits include --- src/xenia/ui/vulkan/vulkan_device.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xenia/ui/vulkan/vulkan_device.cc b/src/xenia/ui/vulkan/vulkan_device.cc index 166a18b01..b8ded460e 100644 --- a/src/xenia/ui/vulkan/vulkan_device.cc +++ b/src/xenia/ui/vulkan/vulkan_device.cc @@ -2,7 +2,7 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * + * Copyright 2017 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ @@ -12,6 +12,7 @@ #include #include +#include #include #include From bc8356bb8359e531c793a2c9fc4a0e46c34361f3 Mon Sep 17 00:00:00 2001 From: sephiroth99 Date: Tue, 25 Apr 2017 03:25:05 -0400 Subject: [PATCH 23/38] Remove usage of non standard identity struct std::identity was removed from the standards, but Visual Studio kept it as an extension. Replace it by std::remove_reference, which does just a little bit more than std::identity does, but without impact in this case. --- src/xenia/base/bit_field.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/xenia/base/bit_field.h b/src/xenia/base/bit_field.h index a089775c9..034f43d9e 100644 --- a/src/xenia/base/bit_field.h +++ b/src/xenia/base/bit_field.h @@ -29,7 +29,8 @@ struct bf { // For enum values, we strip them down to an underlying type. typedef typename std::conditional::value, std::underlying_type, - std::identity>::type::type value_type; + std::remove_reference>::type::type + value_type; inline value_type mask() const { return (((value_type)~0) >> (8 * sizeof(value_type) - n_bits)) << position; } @@ -39,4 +40,4 @@ struct bf { } // namespace xe -#endif // XENIA_BASE_BIT_FIELD_H_ \ No newline at end of file +#endif // XENIA_BASE_BIT_FIELD_H_ From 570e359caa0e8b9fd7468dd63c183579aff1a5e7 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sat, 8 Jul 2017 02:34:11 -0600 Subject: [PATCH 24/38] Support vulkan xcb device for Linux --- src/xenia/ui/vulkan/vulkan.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xenia/ui/vulkan/vulkan.h b/src/xenia/ui/vulkan/vulkan.h index 7a7e64f10..38a4400f7 100644 --- a/src/xenia/ui/vulkan/vulkan.h +++ b/src/xenia/ui/vulkan/vulkan.h @@ -16,6 +16,8 @@ #if XE_PLATFORM_WIN32 #define VK_USE_PLATFORM_WIN32_KHR 1 +#elif XE_PLATFORM_LINUX +#define VK_USE_PLATFORM_XCB_KHR 1 #else #error Platform not yet supported. #endif // XE_PLATFORM_WIN32 From 6bf05d6e63ea6aa9f519b5feba6624d9c53bf94a Mon Sep 17 00:00:00 2001 From: sephiroth99 Date: Wed, 26 Apr 2017 02:11:35 -0400 Subject: [PATCH 25/38] Enable XCB in Vulkan loader on Linux --- third_party/vulkan/loader/premake5.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/third_party/vulkan/loader/premake5.lua b/third_party/vulkan/loader/premake5.lua index ea6fbebf7..e653b278b 100644 --- a/third_party/vulkan/loader/premake5.lua +++ b/third_party/vulkan/loader/premake5.lua @@ -30,6 +30,7 @@ project("vulkan-loader") removefiles("dirent_on_windows.c") filter("platforms:Linux") defines({ + "VK_USE_PLATFORM_XCB_KHR", [[SYSCONFDIR="\"/etc\""]], [[FALLBACK_CONFIG_DIRS="\"/etc/xdg\""]], [[DATADIR="\"/usr/share\""]], From c43845842616f529dfaa7c21d092c1a15fae18a7 Mon Sep 17 00:00:00 2001 From: sephiroth99 Date: Wed, 26 Apr 2017 02:25:12 -0400 Subject: [PATCH 26/38] Enable premake linkgroups when building Linux applications The linkgroups option is a convenience option that makes it possible to specify all the libraries required to build an application (console or GUI) in any order. It also prevents circular dependency issues between libraries. Basically, it surrounds the list of libraries with the start-group/end-group options when calling the linker. --- premake5.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/premake5.lua b/premake5.lua index 6f015fc54..a5ac7f678 100644 --- a/premake5.lua +++ b/premake5.lua @@ -100,6 +100,9 @@ filter("platforms:Linux") "`pkg-config --libs gtk+-3.0`", }) +filter({"platforms:Linux", "kind:*App"}) + linkgroups("On") + filter({"platforms:Linux", "language:C++", "toolset:gcc"}) buildoptions({ "--std=c++11", From 11637af8e9b99f861fbedbe5ec75e83968046c03 Mon Sep 17 00:00:00 2001 From: sephiroth99 Date: Mon, 5 Jun 2017 23:30:20 -0400 Subject: [PATCH 27/38] Add missing Profiler function when profiling is disabled --- src/xenia/base/profiling.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xenia/base/profiling.cc b/src/xenia/base/profiling.cc index c1d474b01..f8841d1f4 100644 --- a/src/xenia/base/profiling.cc +++ b/src/xenia/base/profiling.cc @@ -268,6 +268,7 @@ void Profiler::ToggleDisplay() {} void Profiler::TogglePause() {} void Profiler::set_window(ui::Window* window) {} void Profiler::Present() {} +void Profiler::Flip() {} #endif // XE_OPTION_PROFILING From 7ede34b5936dc8ec21e3ac5be412195cc2f807f2 Mon Sep 17 00:00:00 2001 From: sephiroth99 Date: Tue, 6 Jun 2017 02:04:02 -0400 Subject: [PATCH 28/38] vulkan: render_cache: fix clang compilation --- src/xenia/gpu/vulkan/render_cache.cc | 3 +++ src/xenia/gpu/vulkan/render_cache.h | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc index 02b41219a..8cdcd86f0 100644 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ b/src/xenia/gpu/vulkan/render_cache.cc @@ -903,6 +903,9 @@ CachedTileView* RenderCache::FindTileView(uint32_t base, uint32_t pitch, case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_unknown: format = uint32_t(ColorRenderTargetFormat::k_2_10_10_10_FLOAT); break; + default: + // Other types as-is. + break; } } diff --git a/src/xenia/gpu/vulkan/render_cache.h b/src/xenia/gpu/vulkan/render_cache.h index b6dca40cc..9f9e1bf30 100644 --- a/src/xenia/gpu/vulkan/render_cache.h +++ b/src/xenia/gpu/vulkan/render_cache.h @@ -82,7 +82,7 @@ class CachedTileView { } VkExtent2D GetSize() const { - return {key.tile_width * 80ul, key.tile_height * 16ul}; + return {key.tile_width * 80u, key.tile_height * 16u}; } private: From 1c40e46cd1c2ccae264a119af06274e3a02a0ce8 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sun, 9 Jul 2017 16:00:00 -0600 Subject: [PATCH 29/38] Add Add XCB/Xlib interaction and X11 specific GTK headers/includes --- premake5.lua | 8 ++++---- src/xenia/base/platform_linux.h | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/premake5.lua b/premake5.lua index a5ac7f678..c3c3a9ac8 100644 --- a/premake5.lua +++ b/premake5.lua @@ -87,11 +87,15 @@ filter("platforms:Linux") toolset("clang") buildoptions({ -- "-mlzcnt", -- (don't) Assume lzcnt is supported. + "`pkg-config --cflags gtk+-x11-3.0`" }) links({ "pthread", + "dl", "lz4", "X11", + "xcb", + "X11-xcb", "GL", "GLEW", "vulkan", @@ -113,11 +117,7 @@ filter({"platforms:Linux", "language:C++", "toolset:gcc"}) filter({"platforms:Linux", "language:C++", "toolset:clang"}) buildoptions({ "-std=c++14", -<<<<<<< HEAD "-stdlib=libc++", -======= --- "-stdlib=libc++", -- Seems to happier using gcc's libc++ ->>>>>>> d50e6f18... Add Linux build params for gtk, libvulkan, etc }) links({ }) diff --git a/src/xenia/base/platform_linux.h b/src/xenia/base/platform_linux.h index f77eb1235..2f995e918 100644 --- a/src/xenia/base/platform_linux.h +++ b/src/xenia/base/platform_linux.h @@ -19,13 +19,14 @@ // Xlib/Xcb is used only for GLX/Vulkan interaction, the window management // and input events are done with gtk/gdk #include +#include #include #include #include //Used for window management. Gtk is for GUI and wigets, gdk is for lower -//level events like key presses, mouse events, etc +//level events like key presses, mouse events, window handles, etc #include -#include +#include #endif // XENIA_BASE_PLATFORM_X11_H_ From b65c7e62970e3b1cc12aa9226b3909c42eb8be61 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sun, 9 Jul 2017 16:14:04 -0600 Subject: [PATCH 30/38] vulkan: render_cache: More clang compilation fixes --- src/xenia/gpu/vulkan/render_cache.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc index 8cdcd86f0..90729bde3 100644 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ b/src/xenia/gpu/vulkan/render_cache.cc @@ -760,6 +760,9 @@ bool RenderCache::ParseConfiguration(RenderConfiguration* config) { case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_unknown: config->color[i].format = ColorRenderTargetFormat::k_2_10_10_10_FLOAT; break; + default: + //The rest are good + break; } } } else { @@ -840,7 +843,7 @@ bool RenderCache::ConfigureRenderPass(VkCommandBuffer command_buffer, color_key.edram_format = static_cast(config->color[i].format); target_color_attachments[i] = FindOrCreateTileView(command_buffer, color_key); - if (!target_color_attachments) { + if (!target_color_attachments[i]) { XELOGE("Failed to get tile view for color attachment"); return false; } @@ -1145,6 +1148,9 @@ void RenderCache::BlitToImage(VkCommandBuffer command_buffer, case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_unknown: format = uint32_t(ColorRenderTargetFormat::k_2_10_10_10_FLOAT); break; + default: + //Rest are OK + break; } } @@ -1258,6 +1264,9 @@ void RenderCache::ClearEDRAMColor(VkCommandBuffer command_buffer, case ColorRenderTargetFormat::k_2_10_10_10_FLOAT_unknown: format = ColorRenderTargetFormat::k_2_10_10_10_FLOAT; break; + default: + //Rest are OK + break; } uint32_t tile_width = num_samples == MsaaSamples::k4X ? 40 : 80; From ae30bc12072b758e24d7f616ff23d9a8602c55ea Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sun, 9 Jul 2017 22:10:08 -0600 Subject: [PATCH 31/38] ui:loop_gtk: Use default thread::id constructor instead of explicit id --- src/xenia/ui/loop_gtk.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/xenia/ui/loop_gtk.cc b/src/xenia/ui/loop_gtk.cc index 44bf1c7e4..217e8c518 100644 --- a/src/xenia/ui/loop_gtk.cc +++ b/src/xenia/ui/loop_gtk.cc @@ -26,7 +26,7 @@ class PostedFn { std::unique_ptr Loop::Create() { return std::make_unique(); } -GTKLoop::GTKLoop() : thread_id_(0) { +GTKLoop::GTKLoop() : thread_id_() { gtk_init(nullptr, nullptr); xe::threading::Fence init_fence; thread_ = std::thread([&init_fence, this]() { @@ -65,7 +65,7 @@ gboolean _posted_fn_thunk(gpointer posted_fn) { } void GTKLoop::Post(std::function fn) { - assert_true(thread_id_ != std::thread::id(0)); + assert_true(thread_id_ != std::thread::id()); gdk_threads_add_idle(_posted_fn_thunk, reinterpret_cast(new PostedFn(std::move(fn)))); } @@ -77,7 +77,7 @@ void GTKLoop::PostDelayed(std::function fn, uint64_t delay_millis) { } void GTKLoop::Quit() { - assert_true(thread_id_ != std::thread::id(0)); + assert_true(thread_id_ != std::thread::id()); } From 879d6e979fd9a5d0b2800b4b9a5deb15017d4d8e Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Sun, 9 Jul 2017 22:13:10 -0600 Subject: [PATCH 32/38] Add missing include --- src/xenia/ui/menu_item.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/xenia/ui/menu_item.h b/src/xenia/ui/menu_item.h index e1364d6b6..59c0ce15d 100644 --- a/src/xenia/ui/menu_item.h +++ b/src/xenia/ui/menu_item.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "xenia/ui/ui_event.h" From 03091d1b7188e693896b94139187a0060f8be4da Mon Sep 17 00:00:00 2001 From: sephiroth99 Date: Wed, 26 Apr 2017 02:13:09 -0400 Subject: [PATCH 33/38] Add missing libraries when linking xenia-app on Linux Currently, each module in Xenia is built as a static library (also called archive). On Linux, an archive only contains the object files for that module. So any depedency that module has must be specified by adding those other modules when linking the program, as the dependencies are resolved at that time. --- src/xenia/app/premake5.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 141450980..5803ea4f9 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -8,8 +8,15 @@ project("xenia-app") targetname("xenia") language("C++") links({ + "capstone", "gflags", + "glslang-spirv", "imgui", + "libavcodec", + "libavutil", + "snappy", + "spirv-tools", + "vulkan-loader", "xenia-apu", "xenia-apu-nop", "xenia-base", @@ -21,11 +28,15 @@ project("xenia-app") "xenia-gpu-gl4", "xenia-gpu-null", "xenia-gpu-vulkan", + "xenia-hid", "xenia-hid-nop", "xenia-kernel", "xenia-ui", "xenia-ui-gl", + "xenia-ui-spirv", + "xenia-ui-vulkan", "xenia-vfs", + "xxhash", }) flags({ "WinMain", -- Use WinMain instead of main. From b143b91fbbc371a7433a4fdabfaafaa01c18c2bb Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Mon, 10 Jul 2017 02:00:52 -0600 Subject: [PATCH 34/38] base: threading_linux: Stub out several synchronization constructs --- src/xenia/base/threading_linux.cc | 1 - src/xenia/base/threading_posix.cc | 291 +++++++++++++++++++++++++++++- 2 files changed, 283 insertions(+), 9 deletions(-) diff --git a/src/xenia/base/threading_linux.cc b/src/xenia/base/threading_linux.cc index 6f4a97584..21d5418c7 100644 --- a/src/xenia/base/threading_linux.cc +++ b/src/xenia/base/threading_linux.cc @@ -15,7 +15,6 @@ namespace xe { namespace threading { -void MaybeYield() { pthread_yield(); } } // namespace threading } // namespace xe diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 3089f11b8..1a0bea457 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -15,12 +15,18 @@ #include #include #include +#include #include #include namespace xe { namespace threading { +//TODO(dougvj) +void EnableAffinityConfiguration() { + +} + // uint64_t ticks() { return mach_absolute_time(); } uint32_t current_thread_system_id() { @@ -32,7 +38,16 @@ void set_name(const std::string& name) { } void set_name(std::thread::native_handle_type handle, const std::string& name) { - pthread_setname_np(pthread_self(), name.c_str()); + pthread_setname_np(handle, name.c_str()); +} + +void MaybeYield() { + pthread_yield(); + __sync_synchronize(); +} + +void SyncMemory() { + __sync_synchronize(); } void Sleep(std::chrono::microseconds duration) { @@ -42,11 +57,133 @@ void Sleep(std::chrono::microseconds duration) { // TODO(benvanik): spin while rmtp >0? } -template -class PosixHandle : public T { +//TODO(dougvj) Not sure how to implement the equivalent of this on POSIX. +SleepResult AlertableSleep(std::chrono::microseconds duration) { + sleep(duration.count() / 1000); + return SleepResult::kSuccess; +} + +//TODO(dougvj) We can probably wrap this with pthread_key_t but the type of +//TlsHandle probably needs to be refactored +TlsHandle AllocateTlsHandle() { + assert_always(); +} + +bool FreeTlsHandle(TlsHandle handle) { return true; } + +uintptr_t GetTlsValue(TlsHandle handle) { + assert_always(); +} + +bool SetTlsValue(TlsHandle handle, uintptr_t value) { + assert_always(); +} + +//TODO(dougvj) +class PosixHighResolutionTimer : public HighResolutionTimer { public: - explicit PosixHandle(pthread_t handle) : handle_(handle) {} - ~PosixHandle() override {} + PosixHighResolutionTimer(std::function callback) + : callback_(callback) {} + ~PosixHighResolutionTimer() override { + } + + bool Initialize(std::chrono::milliseconds period) { + assert_always(); + return false; + } + + private: + std::function callback_; +}; + +std::unique_ptr HighResolutionTimer::CreateRepeating( + std::chrono::milliseconds period, std::function callback) { + auto timer = std::make_unique(std::move(callback)); + if (!timer->Initialize(period)) { + return nullptr; + } + return std::unique_ptr(timer.release()); +} + +// TODO(dougvj) There really is no native POSIX handle for a single wait/signal +// construct pthreads is at a lower level with more handles for such a mechanism +// This simple wrapper class could function as our handle, but probably needs +// some more functionality +class PosixCondition { + public: + PosixCondition(): signal_(false) { + pthread_mutex_init(&mutex_, NULL); + pthread_cond_init(&cond_, NULL); + } + + ~PosixCondition() { + pthread_mutex_destroy(&mutex_); + pthread_cond_destroy(&cond_); + } + + void Signal() { + pthread_mutex_lock(&mutex_); + signal_ = true; + pthread_cond_broadcast(&cond_); + pthread_mutex_unlock(&mutex_); + } + + void Reset() { + pthread_mutex_lock(&mutex_); + signal_ = false; + pthread_mutex_unlock(&mutex_); + } + + bool Wait(unsigned int timeout_ms) { + //Assume 0 means no timeout, not instant timeout + if (timeout_ms == 0) { + Wait(); + } + struct timespec time_to_wait; + struct timeval now; + gettimeofday(&now, NULL); + + //Add the number of seconds we want to wait to the current time + time_to_wait.tv_sec = now.tv_sec + (timeout_ms/1000); + //Add the number of nanoseconds we want to wait to the current nanosecond + //stride + long nsec = (now.tv_usec+(timeout_ms % 1000)) * 1000; + //If we overflowed the nanosecond count then we add a second + time_to_wait.tv_sec += nsec/1000000000UL; + //We only add nanoseconds within the 1 second stride + time_to_wait.tv_nsec = nsec % 1000000000UL; + pthread_mutex_lock(&mutex_); + while(!signal_) { + int status = pthread_cond_timedwait(&cond_, &mutex_, &time_to_wait); + if (status == ETIMEDOUT) + return false; //We timed out + } + pthread_mutex_unlock(&mutex_); + return true; //We didn't time out + } + + bool Wait() { + pthread_mutex_lock(&mutex_); + while(!signal_) { + pthread_cond_wait(&cond_, &mutex_); + } + pthread_mutex_unlock(&mutex_); + return true; //Did not time out; + } + + private: + bool signal_; + pthread_cond_t cond_; + pthread_mutex_t mutex_; + +}; + +//Native posix thread handle +template +class PosixThreadHandle : public T { + public: + explicit PosixThreadHandle(pthread_t handle) : handle_(handle) {} + ~PosixThreadHandle() override {} protected: void* native_handle() const override { @@ -56,13 +193,136 @@ class PosixHandle : public T { pthread_t handle_; }; -class PosixThread : public PosixHandle { +//This is wraps a condition object as our handle because posix has no single +//native handle for higher level concurrency constructs such as semaphores +template +class PosixConditionHandle : public T { public: - explicit PosixThread(pthread_t handle) : PosixHandle(handle) {} + ~PosixConditionHandle() override {} + + protected: + void* native_handle() const override { + return reinterpret_cast(const_cast(&handle_)); + } + + PosixCondition handle_; +}; + + +// TODO(dougvj) +WaitResult Wait(WaitHandle* wait_handle, bool is_alertable, + std::chrono::milliseconds timeout) { + assert_always(); + return WaitResult::kFailed; +} + +// TODO(dougvj) +WaitResult SignalAndWait(WaitHandle* wait_handle_to_signal, + WaitHandle* wait_handle_to_wait_on, bool is_alertable, + std::chrono::milliseconds timeout) { + assert_always(); + return WaitResult::kFailed; +} + +// TODO(dougvj) +std::pair WaitMultiple(WaitHandle* wait_handles[], + size_t wait_handle_count, + bool wait_all, bool is_alertable, + std::chrono::milliseconds timeout) { + assert_always(); + return std::pair(WaitResult::kFailed, 0); +} + + +//TODO(dougvj) +class PosixEvent: public PosixConditionHandle { + public: + PosixEvent(bool initial_state, int auto_reset) { assert_always(); } + ~PosixEvent() override = default; + void Set() override { assert_always(); } + void Reset() override { assert_always(); } + void Pulse() override { assert_always(); } + private: + PosixCondition condition_; +}; + +std::unique_ptr Event::CreateManualResetEvent(bool initial_state) { + return std::make_unique(PosixEvent(initial_state, false)); +} + +std::unique_ptr Event::CreateAutoResetEvent(bool initial_state) { + return std::make_unique(PosixEvent(initial_state, true)); +} + +//TODO(dougvj) +class PosixSemaphore : public PosixConditionHandle { + public: + PosixSemaphore(int initial_count, int maximum_count) { assert_always(); } + ~PosixSemaphore() override = default; + bool Release(int release_count, int* out_previous_count) override { + assert_always(); + return false; + } +}; + +std::unique_ptr Semaphore::Create(int initial_count, + int maximum_count) { + return std::make_unique(initial_count, maximum_count); +} + +//TODO(dougvj) +class PosixMutant : public PosixConditionHandle { + public: + PosixMutant(bool initial_owner) { + assert_always(); + } + ~PosixMutant() = default; + bool Release() override { assert_always(); return false; } + private: +}; + +std::unique_ptr Mutant::Create(bool initial_owner) { + return std::make_unique(initial_owner); +} + +//TODO(dougvj) +class PosixTimer : public PosixConditionHandle { + public: + PosixTimer(bool manual_reset) { assert_always(); } + ~PosixTimer() = default; + bool SetOnce(std::chrono::nanoseconds due_time, + std::function opt_callback) override { + assert_always(); + return false; + } + bool SetRepeating(std::chrono::nanoseconds due_time, + std::chrono::milliseconds period, + std::function opt_callback) override { + assert_always(); + return false; + } + bool Cancel() override { + assert_always(); + return false; + } + +}; + +std::unique_ptr Timer::CreateManualResetTimer() { + return std::make_unique(true); +} + +std::unique_ptr Timer::CreateSynchronizationTimer() { + return std::make_unique(false); +} + +class PosixThread : public PosixThreadHandle { + public: + explicit PosixThread(pthread_t handle) : PosixThreadHandle(handle) {} ~PosixThread() = default; void set_name(std::string name) override { - // TODO(DrChat) + pthread_setname_np(handle_, name.c_str()); } uint32_t system_id() const override { return 0; } @@ -141,5 +401,20 @@ std::unique_ptr Thread::Create(CreationParameters params, return std::unique_ptr(new PosixThread(handle)); } +Thread* Thread::GetCurrentThread() { + if (current_thread_) { + return current_thread_.get(); + } + + pthread_t handle = pthread_self(); + + current_thread_ = std::make_unique(handle); + return current_thread_.get(); +} + +void Thread::Exit(int exit_code) { + pthread_exit(reinterpret_cast(exit_code)); +} + } // namespace threading } // namespace xe From 8ced8eb9e4a3f63ae17e47e82a46713e57e9b5a9 Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Thu, 12 May 2016 01:42:30 -0600 Subject: [PATCH 35/38] base: filesystem_posix: Implement missing functionality --- src/xenia/base/filesystem_posix.cc | 141 +++++++++++++++++++++++++++-- 1 file changed, 134 insertions(+), 7 deletions(-) diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index b9125e319..dd3f885d0 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -15,6 +15,8 @@ #include #include #include +#include +#include namespace xe { namespace filesystem { @@ -24,6 +26,7 @@ bool PathExists(const std::wstring& path) { return stat(xe::to_string(path).c_str(), &st) == 0; } + FILE* OpenFile(const std::wstring& path, const char* mode) { auto fixed_path = xe::fix_path_separators(path); return fopen(xe::to_string(fixed_path).c_str(), mode); @@ -33,6 +36,126 @@ bool CreateFolder(const std::wstring& path) { return mkdir(xe::to_string(path).c_str(), 0774); } +static int removeCallback(const char *fpath, const struct stat* sb, + int typeflag, struct FTW* ftwbuf) { + int rv = remove(fpath); + return rv; +} + +bool DeleteFolder(const std::wstring& path) { + return nftw(xe::to_string(path).c_str(), removeCallback, 64, + FTW_DEPTH | FTW_PHYS) == 0 ? true : false; +} + +static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) { + //Linux uses number of seconds since 1/1/1970, and Windows uses + //number of nanoseconds since 1/1/1601 + //so we convert linux time to nanoseconds and then add the number of + //nanoseconds from 1601 to 1970 + //see https://msdn.microsoft.com/en-us/library/ms724228 + uint64_t filetime = filetime = (unixtime * 10000000) + 116444736000000000; + return filetime; +} + +bool IsFolder(const std::wstring& path) { + struct stat st; + if (stat(xe::to_string(path).c_str(), &st) == 0) { + if (S_ISDIR(st.st_mode)) + return true; + } + return false; +} + +bool CreateFile(const std::wstring& path) { + int file = creat(xe::to_string(path).c_str(), 0774); + if (file >= 0) { + close(file); + return true; + } + return false; +} + +bool DeleteFile(const std::wstring& path) { + return (xe::to_string(path).c_str()) == 0 ? true : false; +} + +class PosixFileHandle : public FileHandle { + public: + PosixFileHandle(std::wstring path, int handle) + : FileHandle(std::move(path)), handle_(handle) {} + ~PosixFileHandle() override { + close(handle_); + handle_ = -1; + } + bool Read(size_t file_offset, void* buffer, size_t buffer_length, + size_t* out_bytes_read) override { + + ssize_t out = pread(handle_, buffer, buffer_length, file_offset); + *out_bytes_read = out; + return out >= 0 ? true : false; + + } + bool Write(size_t file_offset, const void* buffer, size_t buffer_length, + size_t* out_bytes_written) override { + ssize_t out = pwrite(handle_, buffer, buffer_length, file_offset); + *out_bytes_written = out; + return out >= 0 ? true : false; + } + void Flush() override { fsync(handle_); } + + private: + int handle_ = -1; +}; + +std::unique_ptr FileHandle::OpenExisting(std::wstring path, + uint32_t desired_access) { + int open_access; + if (desired_access & FileAccess::kGenericRead) { + open_access |= O_RDONLY; + } + if (desired_access & FileAccess::kGenericWrite) { + open_access |= O_WRONLY; + } + if (desired_access & FileAccess::kGenericExecute) { + open_access |= O_RDONLY; + } + if (desired_access & FileAccess::kGenericAll) { + open_access |= O_RDWR; + } + if (desired_access & FileAccess::kFileReadData) { + open_access |= O_RDONLY; + } + if (desired_access & FileAccess::kFileWriteData) { + open_access |= O_WRONLY; + } + if (desired_access & FileAccess::kFileAppendData) { + open_access |= O_APPEND; + } + int handle = open(xe::to_string(path).c_str(), open_access); + if (handle == -1) { + // TODO(benvanik): pick correct response. + return nullptr; + } + return std::make_unique(path, handle); +} + +bool GetInfo(const std::wstring& path, FileInfo* out_info) { + struct stat st; + if (stat(xe::to_string(path).c_str(), &st) == 0) { + if (S_ISDIR(st.st_mode)) { + out_info->type = FileInfo::Type::kDirectory; + } + else { + out_info->type = FileInfo::Type::kFile; + } + out_info->create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime); + out_info->access_timestamp = convertUnixtimeToWinFiletime(st.st_atime); + out_info->write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime); + return true; + } + return false; +} + std::vector ListFiles(const std::wstring& path) { std::vector result; @@ -43,23 +166,27 @@ std::vector ListFiles(const std::wstring& path) { while (auto ent = readdir(dir)) { FileInfo info; + + info.name = xe::to_wstring(ent->d_name); + struct stat st; + stat((xe::to_string(path) + xe::to_string(info.name)).c_str(), &st); + info.create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime); + info.access_timestamp = convertUnixtimeToWinFiletime(st.st_atime); + info.write_timestamp = convertUnixtimeToWinFiletime(st.st_mtime); if (ent->d_type == DT_DIR) { info.type = FileInfo::Type::kDirectory; info.total_size = 0; } else { info.type = FileInfo::Type::kFile; - info.total_size = 0; // TODO(DrChat): Find a way to get this + info.total_size = st.st_size; } - - info.create_timestamp = 0; - info.access_timestamp = 0; - info.write_timestamp = 0; - info.name = xe::to_wstring(ent->d_name); result.push_back(info); } return result; } + } // namespace filesystem -} // namespace xe \ No newline at end of file +} // namespace xe + From a7671fa2cdf0699508a1ee3dd568a8ef77f189fc Mon Sep 17 00:00:00 2001 From: Doug Johnson Date: Mon, 10 Jul 2017 03:27:25 -0600 Subject: [PATCH 36/38] Add C++ lib linker for clang on Linux --- premake5.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/premake5.lua b/premake5.lua index c3c3a9ac8..71b4e0043 100644 --- a/premake5.lua +++ b/premake5.lua @@ -99,6 +99,8 @@ filter("platforms:Linux") "GL", "GLEW", "vulkan", + "c++", + "c++abi" }) linkoptions({ "`pkg-config --libs gtk+-3.0`", From fa3edace6a91fdd03f272993b1a30d762ee1221b Mon Sep 17 00:00:00 2001 From: scribam Date: Wed, 20 Sep 2017 19:30:29 +0200 Subject: [PATCH 37/38] Fix travis BUILD --- .travis.yml | 10 ++++++++-- premake5.lua | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 14b1e1ab5..5f38ca6bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,17 +22,19 @@ matrix: # LLVMGold.so is not installed correctly - env: BUILD=true CONFIG=Release -dist: trusty sudo: required addons: apt: sources: # - ubuntu-toolchain-r-test - - llvm-toolchain-precise + - llvm-toolchain-trusty packages: - clang-3.8 - clang-format-3.8 - libc++-dev + - libc++abi-dev + - libgtk-3-dev + - liblz4-dev git: # We handle submodules ourselves in xenia-build setup. @@ -43,6 +45,10 @@ before_script: - export CC=clang-3.8 # Dump useful info. - $CXX --version + # Add Vulkan dependencies + - wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb + - wget http://mirrors.kernel.org/ubuntu/pool/universe/v/vulkan/libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb + - sudo dpkg -i libvulkan1_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb libvulkan-dev_1.0.42.0+dfsg1-1ubuntu1~16.04.1_amd64.deb # Prepare environment (pull dependencies, build tools). - travis_retry ./xenia-build setup diff --git a/premake5.lua b/premake5.lua index 71b4e0043..b8d71b117 100644 --- a/premake5.lua +++ b/premake5.lua @@ -34,8 +34,8 @@ filter({}) characterset("Unicode") flags({ - --"ExtraWarnings", -- Sets the compiler's maximum warning level. - "FatalWarnings", -- Treat warnings as errors. + "ExtraWarnings", -- Sets the compiler's maximum warning level. + --"FatalWarnings", -- Treat warnings as errors. }) filter("kind:StaticLib") From b6e7e66fbe9831a3e20551ad19dc942dfb6eab59 Mon Sep 17 00:00:00 2001 From: scribam Date: Wed, 20 Sep 2017 22:39:49 +0200 Subject: [PATCH 38/38] Fix travis LINT --- src/xenia/base/exception_handler_linux.cc | 5 +- src/xenia/base/filesystem_posix.cc | 33 +++---- src/xenia/base/math.h | 2 +- src/xenia/base/platform_linux.cc | 1 - src/xenia/base/platform_linux.h | 10 +- src/xenia/base/threading.h | 2 +- src/xenia/base/threading_linux.cc | 5 +- src/xenia/base/threading_posix.cc | 99 ++++++++----------- .../passes/data_flow_analysis_pass.cc | 2 +- .../compiler/passes/value_reduction_pass.cc | 2 +- src/xenia/gpu/command_processor.h | 1 - src/xenia/gpu/gl4/gl4_shader_cache.h | 2 +- src/xenia/gpu/vulkan/render_cache.cc | 6 +- src/xenia/ui/file_picker_gtk.cc | 35 +++---- src/xenia/ui/gl/gl_context.cc | 8 +- src/xenia/ui/gl/gl_context.h | 6 +- src/xenia/ui/gl/gl_context_win.cc | 11 +-- src/xenia/ui/gl/gl_context_win.h | 13 +-- src/xenia/ui/gl/gl_context_x11.cc | 31 +++--- src/xenia/ui/gl/gl_context_x11.h | 17 ++-- src/xenia/ui/loop_gtk.cc | 29 ++---- src/xenia/ui/loop_gtk.h | 4 +- src/xenia/ui/menu_item.h | 2 +- src/xenia/ui/vulkan/vulkan_context.cc | 11 +-- src/xenia/ui/vulkan/vulkan_instance.cc | 15 ++- src/xenia/ui/window_gtk.cc | 67 ++++++------- src/xenia/ui/window_gtk.h | 15 ++- 27 files changed, 176 insertions(+), 258 deletions(-) diff --git a/src/xenia/base/exception_handler_linux.cc b/src/xenia/base/exception_handler_linux.cc index 16fc669ad..bc656a15d 100644 --- a/src/xenia/base/exception_handler_linux.cc +++ b/src/xenia/base/exception_handler_linux.cc @@ -24,13 +24,12 @@ constexpr size_t kMaxHandlerCount = 8; // Executed in order. std::pair handlers_[kMaxHandlerCount]; - void ExceptionHandler::Install(Handler fn, void* data) { - //TODO(dougvj) stub + // TODO(dougvj) stub } void ExceptionHandler::Uninstall(Handler fn, void* data) { - //TODO(dougvj) stub + // TODO(dougvj) stub } } // namespace xe diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc index dd3f885d0..a948717cc 100644 --- a/src/xenia/base/filesystem_posix.cc +++ b/src/xenia/base/filesystem_posix.cc @@ -12,11 +12,11 @@ #include "xenia/base/string.h" #include +#include +#include #include #include #include -#include -#include namespace xe { namespace filesystem { @@ -26,7 +26,6 @@ bool PathExists(const std::wstring& path) { return stat(xe::to_string(path).c_str(), &st) == 0; } - FILE* OpenFile(const std::wstring& path, const char* mode) { auto fixed_path = xe::fix_path_separators(path); return fopen(xe::to_string(fixed_path).c_str(), mode); @@ -36,23 +35,25 @@ bool CreateFolder(const std::wstring& path) { return mkdir(xe::to_string(path).c_str(), 0774); } -static int removeCallback(const char *fpath, const struct stat* sb, - int typeflag, struct FTW* ftwbuf) { +static int removeCallback(const char* fpath, const struct stat* sb, + int typeflag, struct FTW* ftwbuf) { int rv = remove(fpath); return rv; } bool DeleteFolder(const std::wstring& path) { return nftw(xe::to_string(path).c_str(), removeCallback, 64, - FTW_DEPTH | FTW_PHYS) == 0 ? true : false; + FTW_DEPTH | FTW_PHYS) == 0 + ? true + : false; } static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) { - //Linux uses number of seconds since 1/1/1970, and Windows uses - //number of nanoseconds since 1/1/1601 - //so we convert linux time to nanoseconds and then add the number of - //nanoseconds from 1601 to 1970 - //see https://msdn.microsoft.com/en-us/library/ms724228 + // Linux uses number of seconds since 1/1/1970, and Windows uses + // number of nanoseconds since 1/1/1601 + // so we convert linux time to nanoseconds and then add the number of + // nanoseconds from 1601 to 1970 + // see https://msdn.microsoft.com/en-us/library/ms724228 uint64_t filetime = filetime = (unixtime * 10000000) + 116444736000000000; return filetime; } @@ -60,8 +61,7 @@ static uint64_t convertUnixtimeToWinFiletime(time_t unixtime) { bool IsFolder(const std::wstring& path) { struct stat st; if (stat(xe::to_string(path).c_str(), &st) == 0) { - if (S_ISDIR(st.st_mode)) - return true; + if (S_ISDIR(st.st_mode)) return true; } return false; } @@ -89,11 +89,9 @@ class PosixFileHandle : public FileHandle { } bool Read(size_t file_offset, void* buffer, size_t buffer_length, size_t* out_bytes_read) override { - ssize_t out = pread(handle_, buffer, buffer_length, file_offset); *out_bytes_read = out; return out >= 0 ? true : false; - } bool Write(size_t file_offset, const void* buffer, size_t buffer_length, size_t* out_bytes_written) override { @@ -144,8 +142,7 @@ bool GetInfo(const std::wstring& path, FileInfo* out_info) { if (stat(xe::to_string(path).c_str(), &st) == 0) { if (S_ISDIR(st.st_mode)) { out_info->type = FileInfo::Type::kDirectory; - } - else { + } else { out_info->type = FileInfo::Type::kFile; } out_info->create_timestamp = convertUnixtimeToWinFiletime(st.st_ctime); @@ -186,7 +183,5 @@ std::vector ListFiles(const std::wstring& path) { return result; } - } // namespace filesystem } // namespace xe - diff --git a/src/xenia/base/math.h b/src/xenia/base/math.h index 2e87d87d5..d2c58ee3a 100644 --- a/src/xenia/base/math.h +++ b/src/xenia/base/math.h @@ -11,10 +11,10 @@ #define XENIA_BASE_MATH_H_ #include +#include #include #include #include -#include #include "xenia/base/platform.h" #if XE_ARCH_AMD64 diff --git a/src/xenia/base/platform_linux.cc b/src/xenia/base/platform_linux.cc index 053cbd7c4..b90c6f78e 100644 --- a/src/xenia/base/platform_linux.cc +++ b/src/xenia/base/platform_linux.cc @@ -18,5 +18,4 @@ void LaunchBrowser(const char* url) { system(cmd.c_str()); } - } // namespace xe diff --git a/src/xenia/base/platform_linux.h b/src/xenia/base/platform_linux.h index 2f995e918..345be94ab 100644 --- a/src/xenia/base/platform_linux.h +++ b/src/xenia/base/platform_linux.h @@ -18,15 +18,15 @@ // Xlib/Xcb is used only for GLX/Vulkan interaction, the window management // and input events are done with gtk/gdk -#include #include -#include +#include #include +#include #include -//Used for window management. Gtk is for GUI and wigets, gdk is for lower -//level events like key presses, mouse events, window handles, etc -#include +// Used for window management. Gtk is for GUI and wigets, gdk is for lower +// level events like key presses, mouse events, window handles, etc #include +#include #endif // XENIA_BASE_PLATFORM_X11_H_ diff --git a/src/xenia/base/threading.h b/src/xenia/base/threading.h index bb447f282..480b76207 100644 --- a/src/xenia/base/threading.h +++ b/src/xenia/base/threading.h @@ -16,13 +16,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include namespace xe { namespace threading { diff --git a/src/xenia/base/threading_linux.cc b/src/xenia/base/threading_linux.cc index 21d5418c7..3535f3011 100644 --- a/src/xenia/base/threading_linux.cc +++ b/src/xenia/base/threading_linux.cc @@ -13,8 +13,5 @@ #include namespace xe { -namespace threading { - - -} // namespace threading +namespace threading {} // namespace threading } // namespace xe diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 1a0bea457..c8d6f6654 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -14,18 +14,16 @@ #include #include -#include #include +#include #include #include namespace xe { namespace threading { -//TODO(dougvj) -void EnableAffinityConfiguration() { - -} +// TODO(dougvj) +void EnableAffinityConfiguration() {} // uint64_t ticks() { return mach_absolute_time(); } @@ -46,9 +44,7 @@ void MaybeYield() { __sync_synchronize(); } -void SyncMemory() { - __sync_synchronize(); -} +void SyncMemory() { __sync_synchronize(); } void Sleep(std::chrono::microseconds duration) { timespec rqtp = {time_t(duration.count() / 1000000), @@ -57,35 +53,28 @@ void Sleep(std::chrono::microseconds duration) { // TODO(benvanik): spin while rmtp >0? } -//TODO(dougvj) Not sure how to implement the equivalent of this on POSIX. +// TODO(dougvj) Not sure how to implement the equivalent of this on POSIX. SleepResult AlertableSleep(std::chrono::microseconds duration) { sleep(duration.count() / 1000); return SleepResult::kSuccess; } -//TODO(dougvj) We can probably wrap this with pthread_key_t but the type of -//TlsHandle probably needs to be refactored -TlsHandle AllocateTlsHandle() { - assert_always(); -} +// TODO(dougvj) We can probably wrap this with pthread_key_t but the type of +// TlsHandle probably needs to be refactored +TlsHandle AllocateTlsHandle() { assert_always(); } bool FreeTlsHandle(TlsHandle handle) { return true; } -uintptr_t GetTlsValue(TlsHandle handle) { - assert_always(); -} +uintptr_t GetTlsValue(TlsHandle handle) { assert_always(); } -bool SetTlsValue(TlsHandle handle, uintptr_t value) { - assert_always(); -} +bool SetTlsValue(TlsHandle handle, uintptr_t value) { assert_always(); } -//TODO(dougvj) +// TODO(dougvj) class PosixHighResolutionTimer : public HighResolutionTimer { public: PosixHighResolutionTimer(std::function callback) : callback_(callback) {} - ~PosixHighResolutionTimer() override { - } + ~PosixHighResolutionTimer() override {} bool Initialize(std::chrono::milliseconds period) { assert_always(); @@ -111,7 +100,7 @@ std::unique_ptr HighResolutionTimer::CreateRepeating( // some more functionality class PosixCondition { public: - PosixCondition(): signal_(false) { + PosixCondition() : signal_(false) { pthread_mutex_init(&mutex_, NULL); pthread_cond_init(&cond_, NULL); } @@ -135,7 +124,7 @@ class PosixCondition { } bool Wait(unsigned int timeout_ms) { - //Assume 0 means no timeout, not instant timeout + // Assume 0 means no timeout, not instant timeout if (timeout_ms == 0) { Wait(); } @@ -143,42 +132,40 @@ class PosixCondition { struct timeval now; gettimeofday(&now, NULL); - //Add the number of seconds we want to wait to the current time - time_to_wait.tv_sec = now.tv_sec + (timeout_ms/1000); - //Add the number of nanoseconds we want to wait to the current nanosecond - //stride - long nsec = (now.tv_usec+(timeout_ms % 1000)) * 1000; - //If we overflowed the nanosecond count then we add a second - time_to_wait.tv_sec += nsec/1000000000UL; - //We only add nanoseconds within the 1 second stride + // Add the number of seconds we want to wait to the current time + time_to_wait.tv_sec = now.tv_sec + (timeout_ms / 1000); + // Add the number of nanoseconds we want to wait to the current nanosecond + // stride + long nsec = (now.tv_usec + (timeout_ms % 1000)) * 1000; + // If we overflowed the nanosecond count then we add a second + time_to_wait.tv_sec += nsec / 1000000000UL; + // We only add nanoseconds within the 1 second stride time_to_wait.tv_nsec = nsec % 1000000000UL; pthread_mutex_lock(&mutex_); - while(!signal_) { + while (!signal_) { int status = pthread_cond_timedwait(&cond_, &mutex_, &time_to_wait); - if (status == ETIMEDOUT) - return false; //We timed out + if (status == ETIMEDOUT) return false; // We timed out } pthread_mutex_unlock(&mutex_); - return true; //We didn't time out + return true; // We didn't time out } bool Wait() { pthread_mutex_lock(&mutex_); - while(!signal_) { + while (!signal_) { pthread_cond_wait(&cond_, &mutex_); } pthread_mutex_unlock(&mutex_); - return true; //Did not time out; + return true; // Did not time out; } private: bool signal_; pthread_cond_t cond_; pthread_mutex_t mutex_; - }; -//Native posix thread handle +// Native posix thread handle template class PosixThreadHandle : public T { public: @@ -193,8 +180,8 @@ class PosixThreadHandle : public T { pthread_t handle_; }; -//This is wraps a condition object as our handle because posix has no single -//native handle for higher level concurrency constructs such as semaphores +// This is wraps a condition object as our handle because posix has no single +// native handle for higher level concurrency constructs such as semaphores template class PosixConditionHandle : public T { public: @@ -208,10 +195,9 @@ class PosixConditionHandle : public T { PosixCondition handle_; }; - // TODO(dougvj) WaitResult Wait(WaitHandle* wait_handle, bool is_alertable, - std::chrono::milliseconds timeout) { + std::chrono::milliseconds timeout) { assert_always(); return WaitResult::kFailed; } @@ -233,15 +219,15 @@ std::pair WaitMultiple(WaitHandle* wait_handles[], return std::pair(WaitResult::kFailed, 0); } - -//TODO(dougvj) -class PosixEvent: public PosixConditionHandle { +// TODO(dougvj) +class PosixEvent : public PosixConditionHandle { public: PosixEvent(bool initial_state, int auto_reset) { assert_always(); } ~PosixEvent() override = default; void Set() override { assert_always(); } void Reset() override { assert_always(); } void Pulse() override { assert_always(); } + private: PosixCondition condition_; }; @@ -254,7 +240,7 @@ std::unique_ptr Event::CreateAutoResetEvent(bool initial_state) { return std::make_unique(PosixEvent(initial_state, true)); } -//TODO(dougvj) +// TODO(dougvj) class PosixSemaphore : public PosixConditionHandle { public: PosixSemaphore(int initial_count, int maximum_count) { assert_always(); } @@ -270,22 +256,22 @@ std::unique_ptr Semaphore::Create(int initial_count, return std::make_unique(initial_count, maximum_count); } -//TODO(dougvj) +// TODO(dougvj) class PosixMutant : public PosixConditionHandle { public: - PosixMutant(bool initial_owner) { - assert_always(); - } + PosixMutant(bool initial_owner) { assert_always(); } ~PosixMutant() = default; - bool Release() override { assert_always(); return false; } - private: + bool Release() override { + assert_always(); + return false; + } }; std::unique_ptr Mutant::Create(bool initial_owner) { return std::make_unique(initial_owner); } -//TODO(dougvj) +// TODO(dougvj) class PosixTimer : public PosixConditionHandle { public: PosixTimer(bool manual_reset) { assert_always(); } @@ -305,7 +291,6 @@ class PosixTimer : public PosixConditionHandle { assert_always(); return false; } - }; std::unique_ptr Timer::CreateManualResetTimer() { diff --git a/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc b/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc index 5f403c738..622af656b 100644 --- a/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc +++ b/src/xenia/cpu/compiler/passes/data_flow_analysis_pass.cc @@ -23,8 +23,8 @@ #include #pragma warning(pop) #else -#include #include +#include #endif // XE_COMPILER_MSVC namespace xe { diff --git a/src/xenia/cpu/compiler/passes/value_reduction_pass.cc b/src/xenia/cpu/compiler/passes/value_reduction_pass.cc index 635290d67..02ec9e757 100644 --- a/src/xenia/cpu/compiler/passes/value_reduction_pass.cc +++ b/src/xenia/cpu/compiler/passes/value_reduction_pass.cc @@ -22,8 +22,8 @@ #include #pragma warning(pop) #else -#include #include +#include #endif // XE_COMPILER_MSVC namespace xe { diff --git a/src/xenia/gpu/command_processor.h b/src/xenia/gpu/command_processor.h index e8f7fffec..a418dd683 100644 --- a/src/xenia/gpu/command_processor.h +++ b/src/xenia/gpu/command_processor.h @@ -240,4 +240,3 @@ class CommandProcessor { } // namespace xe #endif // XENIA_GPU_COMMAND_PROCESSOR_H_ - diff --git a/src/xenia/gpu/gl4/gl4_shader_cache.h b/src/xenia/gpu/gl4/gl4_shader_cache.h index 59eaf665e..9c5c77cb2 100644 --- a/src/xenia/gpu/gl4/gl4_shader_cache.h +++ b/src/xenia/gpu/gl4/gl4_shader_cache.h @@ -11,10 +11,10 @@ #define XENIA_GPU_GL4_SHADER_CACHE_H_ #include -#include #include #include #include +#include #include "xenia/gpu/xenos.h" diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc index 90729bde3..d3a4b5a66 100644 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ b/src/xenia/gpu/vulkan/render_cache.cc @@ -761,7 +761,7 @@ bool RenderCache::ParseConfiguration(RenderConfiguration* config) { config->color[i].format = ColorRenderTargetFormat::k_2_10_10_10_FLOAT; break; default: - //The rest are good + // The rest are good break; } } @@ -1149,7 +1149,7 @@ void RenderCache::BlitToImage(VkCommandBuffer command_buffer, format = uint32_t(ColorRenderTargetFormat::k_2_10_10_10_FLOAT); break; default: - //Rest are OK + // Rest are OK break; } } @@ -1265,7 +1265,7 @@ void RenderCache::ClearEDRAMColor(VkCommandBuffer command_buffer, format = ColorRenderTargetFormat::k_2_10_10_10_FLOAT; break; default: - //Rest are OK + // Rest are OK break; } diff --git a/src/xenia/ui/file_picker_gtk.cc b/src/xenia/ui/file_picker_gtk.cc index 8dc52eadc..dce28772d 100644 --- a/src/xenia/ui/file_picker_gtk.cc +++ b/src/xenia/ui/file_picker_gtk.cc @@ -9,11 +9,11 @@ #include "xenia/ui/file_picker.h" +#include +#include +#include #include "xenia/base/assert.h" #include "xenia/base/platform_linux.h" -#include -#include -#include namespace xe { namespace ui { @@ -36,39 +36,34 @@ GtkFilePicker::GtkFilePicker() = default; GtkFilePicker::~GtkFilePicker() = default; - bool GtkFilePicker::Show(void* parent_window_handle) { // TODO(benvanik): FileSaveDialog. assert_true(mode() == Mode::kOpen); // TODO(benvanik): folder dialogs. assert_true(type() == Type::kFile); - GtkWidget *dialog; + GtkWidget* dialog; gint res; - dialog = gtk_file_chooser_dialog_new ("Open File", - (GtkWindow*)parent_window_handle, - GTK_FILE_CHOOSER_ACTION_OPEN, - "_Cancel", - GTK_RESPONSE_CANCEL, - "_Open", - GTK_RESPONSE_ACCEPT, - NULL); + dialog = gtk_file_chooser_dialog_new( + "Open File", (GtkWindow*)parent_window_handle, + GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", GTK_RESPONSE_CANCEL, "_Open", + GTK_RESPONSE_ACCEPT, NULL); - res = gtk_dialog_run (GTK_DIALOG (dialog)); - char *filename; + res = gtk_dialog_run(GTK_DIALOG(dialog)); + char* filename; if (res == GTK_RESPONSE_ACCEPT) { - GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog); - filename = gtk_file_chooser_get_filename (chooser); + GtkFileChooser* chooser = GTK_FILE_CHOOSER(dialog); + filename = gtk_file_chooser_get_filename(chooser); std::vector selected_files; std::wstring_convert> converter; std::wstring ws_filename = converter.from_bytes(filename); selected_files.push_back(ws_filename); set_selected_files(selected_files); - gtk_widget_destroy (dialog); + gtk_widget_destroy(dialog); return true; } - gtk_widget_destroy (dialog); - return false;; + gtk_widget_destroy(dialog); + return false; } } // namespace ui diff --git a/src/xenia/ui/gl/gl_context.cc b/src/xenia/ui/gl/gl_context.cc index 24c4f75ce..a1c94ef9e 100644 --- a/src/xenia/ui/gl/gl_context.cc +++ b/src/xenia/ui/gl/gl_context.cc @@ -21,7 +21,6 @@ #include "xenia/ui/gl/gl_immediate_drawer.h" #include "xenia/ui/window.h" - DEFINE_bool(thread_safe_gl, false, "Only allow one GL context to be active at a time."); @@ -40,7 +39,6 @@ namespace xe { namespace ui { namespace gl { - std::recursive_mutex GLContext::global_gl_mutex_; void GLContext::FatalGLError(std::string error) { @@ -51,10 +49,8 @@ void GLContext::FatalGLError(std::string error) { "of supported GPUs."); } - - GLContext::GLContext(GraphicsProvider* provider, Window* target_window) - : GraphicsContext(provider, target_window) { } + : GraphicsContext(provider, target_window) {} GLContext::~GLContext() {} @@ -218,8 +214,6 @@ ImmediateDrawer* GLContext::immediate_drawer() { return immediate_drawer_.get(); } - - bool GLContext::WasLost() { if (!robust_access_supported_) { // Can't determine if we lost the context. diff --git a/src/xenia/ui/gl/gl_context.h b/src/xenia/ui/gl/gl_context.h index 8e49b80df..d71e209b2 100644 --- a/src/xenia/ui/gl/gl_context.h +++ b/src/xenia/ui/gl/gl_context.h @@ -29,7 +29,6 @@ DECLARE_bool(gl_debug); DECLARE_bool(gl_debug_output); DECLARE_bool(gl_debug_output_synchronous); - namespace xe { namespace ui { namespace gl { @@ -69,6 +68,7 @@ class GLContext : public GraphicsContext { void AssertExtensionsPresent(); void DebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message); + private: friend class GLProvider; @@ -79,15 +79,11 @@ class GLContext : public GraphicsContext { GLContext* parent_context); private: - - static void GLAPIENTRY DebugMessageThunk(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, GLvoid* user_param); - - }; } // namespace gl diff --git a/src/xenia/ui/gl/gl_context_win.cc b/src/xenia/ui/gl/gl_context_win.cc index c48e4a55e..0ca66146c 100644 --- a/src/xenia/ui/gl/gl_context_win.cc +++ b/src/xenia/ui/gl/gl_context_win.cc @@ -24,23 +24,20 @@ #include "third_party/GL/wglew.h" - namespace xe { namespace ui { namespace gl { - 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::unique_ptr GLContext::Create(GraphicsProvider* provider, Window* target_window, GLContext* share_context) { auto context = - std::unique_ptr(new WGLContext(provider, target_window)); + std::unique_ptr(new WGLContext(provider, target_window)); if (!context->Initialize(share_context)) { return nullptr; } @@ -48,11 +45,10 @@ std::unique_ptr GLContext::Create(GraphicsProvider* provider, return context; } - std::unique_ptr GLContext::CreateOffscreen( - GraphicsProvider* provider, GLContext* parent_context) { + GraphicsProvider* provider, GLContext* parent_context) { return WGLContext::CreateOffscreen(provider, - static_cast(parent_context)); + static_cast(parent_context)); } WGLContext::WGLContext(GraphicsProvider* provider, Window* target_window) @@ -296,7 +292,6 @@ void WGLContext::ClearCurrent() { } } - void WGLContext::BeginSwap() { SCOPE_profile_cpu_i("gpu", "xe::ui::gl::WGLContext::BeginSwap"); float clear_color[] = {238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.0f}; diff --git a/src/xenia/ui/gl/gl_context_win.h b/src/xenia/ui/gl/gl_context_win.h index 392418f81..772de4d3e 100644 --- a/src/xenia/ui/gl/gl_context_win.h +++ b/src/xenia/ui/gl/gl_context_win.h @@ -14,9 +14,9 @@ #include -#include "xenia/ui/gl/gl_context.h" #include "xenia/ui/gl/blitter.h" #include "xenia/ui/gl/gl.h" +#include "xenia/ui/gl/gl_context.h" #include "xenia/ui/graphics_context.h" typedef struct HDC__* HDC; @@ -33,7 +33,6 @@ class WGLContext : public GLContext { public: ~WGLContext() override; - bool is_current() override; bool MakeCurrent() override; void ClearCurrent() override; @@ -41,25 +40,21 @@ class WGLContext : public GLContext { void BeginSwap() override; void EndSwap() override; - protected: friend class GLContext; WGLContext(GraphicsProvider* provider, Window* target_window); - static std::unique_ptr CreateOffscreen(GraphicsProvider* provider, - WGLContext* parent_context); + static std::unique_ptr CreateOffscreen( + GraphicsProvider* provider, WGLContext* parent_context); bool Initialize(GLContext* share_context) override; - void* handle() override {return glrc_;}; + void* handle() override { return glrc_; } private: - - HDC dc_ = nullptr; HGLRC glrc_ = nullptr; std::unique_ptr glew_context_; std::unique_ptr wglew_context_; - }; } // namespace gl diff --git a/src/xenia/ui/gl/gl_context_x11.cc b/src/xenia/ui/gl/gl_context_x11.cc index bc35685da..fc4b3176b 100644 --- a/src/xenia/ui/gl/gl_context_x11.cc +++ b/src/xenia/ui/gl/gl_context_x11.cc @@ -11,9 +11,11 @@ #include +#include #include #include +#include "third_party/GL/glxew.h" #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" @@ -21,27 +23,21 @@ #include "xenia/base/profiling.h" #include "xenia/ui/gl/gl_immediate_drawer.h" #include "xenia/ui/window.h" -#include "third_party/GL/glxew.h" -#include namespace xe { namespace ui { namespace gl { - - thread_local GLEWContext* tls_glew_context_ = nullptr; thread_local GLXEWContext* tls_glxew_context_ = nullptr; extern "C" GLEWContext* glewGetContext() { return tls_glew_context_; } extern "C" GLXEWContext* glxewGetContext() { return tls_glxew_context_; } - - std::unique_ptr GLContext::Create(GraphicsProvider* provider, Window* target_window, GLContext* share_context) { auto context = - std::unique_ptr(new GLXContext(provider, target_window)); + std::unique_ptr(new GLXContext(provider, target_window)); if (!context->Initialize(share_context)) { return nullptr; } @@ -50,9 +46,9 @@ std::unique_ptr GLContext::Create(GraphicsProvider* provider, } std::unique_ptr GLContext::CreateOffscreen( - GraphicsProvider* provider, GLContext* parent_context) { + GraphicsProvider* provider, GLContext* parent_context) { return GLXContext::CreateOffscreen(provider, - static_cast(parent_context)); + static_cast(parent_context)); } GLXContext::GLXContext(GraphicsProvider* provider, Window* target_window) @@ -74,8 +70,6 @@ GLXContext::~GLXContext() { } } - - bool GLXContext::Initialize(GLContext* share_context) { GtkWidget* window = GTK_WIDGET(target_window_->native_handle()); GtkWidget* draw_area = gtk_drawing_area_new(); @@ -90,8 +84,8 @@ bool GLXContext::Initialize(GLContext* share_context) { Display* display = gdk_x11_display_get_xdisplay(gdk_display); disp_ = display; ::Window root = gdk_x11_get_default_root_xwindow(); - static int vis_attrib_list[] = - {GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None}; + static int vis_attrib_list[] = {GLX_RGBA, GLX_DEPTH_SIZE, 24, + GLX_DOUBLEBUFFER, None}; XVisualInfo* vi = glXChooseVisual(display, 0, vis_attrib_list); if (vi == NULL) { FatalGLError("No matching visuals for X display"); @@ -151,8 +145,8 @@ bool GLXContext::Initialize(GLContext* share_context) { GLXContext* share_context_glx = static_cast(share_context); glx_context_ = glXCreateContextAttribsARB( display, nullptr, - share_context ? share_context_glx->glx_context_ : nullptr, True, - attrib_list); + share_context ? share_context_glx->glx_context_ : nullptr, True, + attrib_list); glXMakeCurrent(display, 0, nullptr); glXDestroyContext(display, temp_context); if (!glx_context_) { @@ -222,7 +216,8 @@ std::unique_ptr GLXContext::CreateOffscreen( robust_access_supported ? GLX_LOSE_CONTEXT_ON_RESET_ARB : 0, 0}; new_glrc = glXCreateContextAttribsARB(parent_context->disp_, nullptr, - parent_context->glx_context_, True, attrib_list); + parent_context->glx_context_, True, + attrib_list); if (!new_glrc) { FatalGLError("Could not create shared context."); return nullptr; @@ -271,13 +266,10 @@ std::unique_ptr GLXContext::CreateOffscreen( return new_context; } - - bool GLXContext::is_current() { return tls_glew_context_ == glew_context_.get(); } - bool GLXContext::MakeCurrent() { SCOPE_profile_cpu_f("gpu"); if (FLAGS_thread_safe_gl) { @@ -308,7 +300,6 @@ void GLXContext::ClearCurrent() { } } - void GLXContext::BeginSwap() { SCOPE_profile_cpu_i("gpu", "xe::ui::gl::GLXContext::BeginSwap"); float clear_color[] = {238 / 255.0f, 238 / 255.0f, 238 / 255.0f, 1.0f}; diff --git a/src/xenia/ui/gl/gl_context_x11.h b/src/xenia/ui/gl/gl_context_x11.h index 789df284f..6eea7fdb7 100644 --- a/src/xenia/ui/gl/gl_context_x11.h +++ b/src/xenia/ui/gl/gl_context_x11.h @@ -14,16 +14,15 @@ #include -#include "xenia/ui/gl/gl_context.h" -#include "xenia/ui/gl/blitter.h" -#include "xenia/ui/gl/gl.h" -#include "xenia/ui/graphics_context.h" #include "third_party/GL/glxew.h" #include "xenia/base/platform_linux.h" +#include "xenia/ui/gl/blitter.h" +#include "xenia/ui/gl/gl.h" +#include "xenia/ui/gl/gl_context.h" +#include "xenia/ui/graphics_context.h" DECLARE_bool(thread_safe_gl); - namespace xe { namespace ui { namespace gl { @@ -35,7 +34,6 @@ class GLXContext : public GLContext { public: ~GLXContext() override; - bool is_current() override; bool MakeCurrent() override; @@ -44,13 +42,12 @@ class GLXContext : public GLContext { void BeginSwap() override; void EndSwap() override; - protected: - static std::unique_ptr CreateOffscreen(GraphicsProvider* provider, - GLXContext* parent_context); + static std::unique_ptr CreateOffscreen( + GraphicsProvider* provider, GLXContext* parent_context); bool Initialize(GLContext* share_context) override; - void* handle() override {return glx_context_;} + void* handle() override { return glx_context_; } private: friend class GLContext; diff --git a/src/xenia/ui/loop_gtk.cc b/src/xenia/ui/loop_gtk.cc index 217e8c518..8beb967e5 100644 --- a/src/xenia/ui/loop_gtk.cc +++ b/src/xenia/ui/loop_gtk.cc @@ -14,7 +14,6 @@ namespace xe { namespace ui { - class PostedFn { public: explicit PostedFn(std::function fn) : fn_(std::move(fn)) {} @@ -28,7 +27,7 @@ std::unique_ptr Loop::Create() { return std::make_unique(); } GTKLoop::GTKLoop() : thread_id_() { gtk_init(nullptr, nullptr); - xe::threading::Fence init_fence; + xe::threading::Fence init_fence; thread_ = std::thread([&init_fence, this]() { xe::threading::set_name("GTK Loop"); @@ -47,39 +46,31 @@ GTKLoop::~GTKLoop() { thread_.join(); } -void GTKLoop::ThreadMain() { - - gtk_main(); - -} +void GTKLoop::ThreadMain() { gtk_main(); } bool GTKLoop::is_on_loop_thread() { return thread_id_ == std::this_thread::get_id(); } - gboolean _posted_fn_thunk(gpointer posted_fn) { - PostedFn* Fn = reinterpret_cast(posted_fn); - Fn->Call(); - return G_SOURCE_REMOVE; + PostedFn* Fn = reinterpret_cast(posted_fn); + Fn->Call(); + return G_SOURCE_REMOVE; } void GTKLoop::Post(std::function fn) { assert_true(thread_id_ != std::thread::id()); gdk_threads_add_idle(_posted_fn_thunk, - reinterpret_cast(new PostedFn(std::move(fn)))); + reinterpret_cast(new PostedFn(std::move(fn)))); } - void GTKLoop::PostDelayed(std::function fn, uint64_t delay_millis) { - gdk_threads_add_timeout(delay_millis, _posted_fn_thunk, - reinterpret_cast(new PostedFn(std::move(fn)))); + gdk_threads_add_timeout( + delay_millis, _posted_fn_thunk, + reinterpret_cast(new PostedFn(std::move(fn)))); } -void GTKLoop::Quit() { - assert_true(thread_id_ != std::thread::id()); - -} +void GTKLoop::Quit() { assert_true(thread_id_ != std::thread::id()); } void GTKLoop::AwaitQuit() { quit_fence_.Wait(); } diff --git a/src/xenia/ui/loop_gtk.h b/src/xenia/ui/loop_gtk.h index 6071851eb..4e24d8915 100644 --- a/src/xenia/ui/loop_gtk.h +++ b/src/xenia/ui/loop_gtk.h @@ -35,15 +35,13 @@ class GTKLoop : public Loop { void Quit() override; void AwaitQuit() override; - private: + private: void ThreadMain(); std::thread::id thread_id_; std::thread thread_; xe::threading::Fence quit_fence_; - - }; } // namespace ui diff --git a/src/xenia/ui/menu_item.h b/src/xenia/ui/menu_item.h index 59c0ce15d..0ad9db54b 100644 --- a/src/xenia/ui/menu_item.h +++ b/src/xenia/ui/menu_item.h @@ -12,8 +12,8 @@ #include #include -#include #include +#include #include "xenia/ui/ui_event.h" diff --git a/src/xenia/ui/vulkan/vulkan_context.cc b/src/xenia/ui/vulkan/vulkan_context.cc index cef115278..da3d323be 100644 --- a/src/xenia/ui/vulkan/vulkan_context.cc +++ b/src/xenia/ui/vulkan/vulkan_context.cc @@ -73,16 +73,15 @@ bool VulkanContext::Initialize() { assert(GDK_IS_X11_DISPLAY(gdk_display)); xcb_connection_t* connection = XGetXCBConnection(gdk_x11_display_get_xdisplay(gdk_display)); - xcb_window_t window = gdk_x11_window_get_xid( - gtk_widget_get_window(window_handle)); + xcb_window_t window = + gdk_x11_window_get_xid(gtk_widget_get_window(window_handle)); VkXcbSurfaceCreateInfoKHR create_info; create_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; create_info.pNext = nullptr; create_info.flags = 0; - create_info.connection = static_cast - (target_window_->native_platform_handle()); - create_info.window = - static_cast(window); + create_info.connection = static_cast( + target_window_->native_platform_handle()); + create_info.window = static_cast(window); auto err = vkCreateXcbSurfaceKHR(*provider->instance(), &create_info, nullptr, &surface); CheckResult(err, "vkCreateXcbSurfaceKHR"); diff --git a/src/xenia/ui/vulkan/vulkan_instance.cc b/src/xenia/ui/vulkan/vulkan_instance.cc index 6aaa8c41c..3c51dfa1a 100644 --- a/src/xenia/ui/vulkan/vulkan_instance.cc +++ b/src/xenia/ui/vulkan/vulkan_instance.cc @@ -397,18 +397,17 @@ bool VulkanInstance::QueryDevices(Window* any_target_window) { assert(GDK_IS_X11_DISPLAY(gdk_display)); xcb_connection_t* connection = XGetXCBConnection(gdk_x11_display_get_xdisplay(gdk_display)); - xcb_window_t window = gdk_x11_window_get_xid( - gtk_widget_get_window(window_handle)); + xcb_window_t window = + gdk_x11_window_get_xid(gtk_widget_get_window(window_handle)); VkXcbSurfaceCreateInfoKHR create_info; create_info.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; create_info.pNext = nullptr; create_info.flags = 0; - create_info.connection = static_cast - (any_target_window->native_platform_handle()); - create_info.window = - static_cast(window); - auto err = vkCreateXcbSurfaceKHR(handle, &create_info, - nullptr, &any_surface); + create_info.connection = static_cast( + any_target_window->native_platform_handle()); + create_info.window = static_cast(window); + auto err = + vkCreateXcbSurfaceKHR(handle, &create_info, nullptr, &any_surface); CheckResult(err, "vkCreateXcbSurfaceKHR"); #else #error Unsupported GDK Backend on Linux. diff --git a/src/xenia/ui/window_gtk.cc b/src/xenia/ui/window_gtk.cc index fcf0f4e30..2e94f6ddc 100644 --- a/src/xenia/ui/window_gtk.cc +++ b/src/xenia/ui/window_gtk.cc @@ -17,7 +17,6 @@ namespace xe { namespace ui { - class FnWrapper { public: explicit FnWrapper(std::function fn) : fn_(std::move(fn)) {} @@ -161,12 +160,12 @@ void GTKWindow::set_focus(bool value) { if (value) { gtk_window_activate_focus(GTK_WINDOW(window_)); } else { - // TODO(dougvj) Check to see if we need to do somethign here to unset + // TODO(dougvj) Check to see if we need to do something here to unset // the focus. } - } else { - has_focus_ = value; - } + } else { + has_focus_ = value; + } } void GTKWindow::Resize(int32_t width, int32_t height) { @@ -219,8 +218,6 @@ void GTKWindow::OnMainMenuChange() { } } - - bool GTKWindow::HandleWindowOwnerChange(GdkEventOwnerChange* event) { if (event->type == GDK_OWNER_CHANGE) { if (event->reason == GDK_OWNER_CHANGE_DESTROY) { @@ -231,8 +228,8 @@ bool GTKWindow::HandleWindowOwnerChange(GdkEventOwnerChange* event) { OnClose(); } return true; - } - return false; + } + return false; } bool GTKWindow::HandleWindowResize(GdkEventConfigure* event) { @@ -244,8 +241,6 @@ bool GTKWindow::HandleWindowResize(GdkEventConfigure* event) { return false; } - - bool GTKWindow::HandleWindowVisibility(GdkEventVisibility* event) { // TODO(dougvj) The gdk docs say that this is deprecated because modern window // managers composite everything and nothing is truly hidden. @@ -258,8 +253,8 @@ bool GTKWindow::HandleWindowVisibility(GdkEventVisibility* event) { OnHidden(&e); } return true; - } - return false; + } + return false; } bool GTKWindow::HandleWindowFocus(GdkEventFocus* event) { @@ -274,8 +269,8 @@ bool GTKWindow::HandleWindowFocus(GdkEventFocus* event) { OnGotFocus(&e); } return true; - } - return false; + } + return false; } bool GTKWindow::HandleMouse(GdkEventAny* event) { @@ -326,26 +321,26 @@ bool GTKWindow::HandleMouse(GdkEventAny* event) { dy = e->delta_y; break; } - } + } - auto e = MouseEvent(this, button, x, y, dx, dy); - switch (event->type) { - case GDK_BUTTON_PRESS: - OnMouseDown(&e); - break; - case GDK_BUTTON_RELEASE: - OnMouseUp(&e); - break; - case GDK_MOTION_NOTIFY: - OnMouseMove(&e); - break; - case GDK_SCROLL: - OnMouseWheel(&e); - break; - default: - return false; - } - return e.is_handled(); + auto e = MouseEvent(this, button, x, y, dx, dy); + switch (event->type) { + case GDK_BUTTON_PRESS: + OnMouseDown(&e); + break; + case GDK_BUTTON_RELEASE: + OnMouseUp(&e); + break; + case GDK_MOTION_NOTIFY: + OnMouseMove(&e); + break; + case GDK_SCROLL: + OnMouseWheel(&e); + break; + default: + return false; + } + return e.is_handled(); } bool GTKWindow::HandleKeyboard(GdkEventKey* event) { @@ -364,8 +359,8 @@ bool GTKWindow::HandleKeyboard(GdkEventKey* event) { case GDK_KEY_RELEASE: OnKeyUp(&e); break; -// TODO(dougvj) GDK doesn't have a KEY CHAR event, so we will have to -// figure out its equivalent here to call OnKeyChar(&e); + // TODO(dougvj) GDK doesn't have a KEY CHAR event, so we will have to + // figure out its equivalent here to call OnKeyChar(&e); default: return false; } diff --git a/src/xenia/ui/window_gtk.h b/src/xenia/ui/window_gtk.h index f6e18753f..b19248e18 100644 --- a/src/xenia/ui/window_gtk.h +++ b/src/xenia/ui/window_gtk.h @@ -13,9 +13,9 @@ #include #include +#include "xenia/base/platform_linux.h" #include "xenia/ui/menu_item.h" #include "xenia/ui/window.h" -#include "xenia/base/platform_linux.h" namespace xe { namespace ui { @@ -27,9 +27,10 @@ class GTKWindow : public Window { GTKWindow(Loop* loop, const std::wstring& title); ~GTKWindow() override; - NativePlatformHandle native_platform_handle() const override {return nullptr;} - NativeWindowHandle native_handle() const override { return window_;} - + NativePlatformHandle native_platform_handle() const override { + return nullptr; + } + NativeWindowHandle native_handle() const override { return window_; } bool set_title(const std::wstring& title) override; @@ -60,7 +61,6 @@ class GTKWindow : public Window { void OnResize(UIEvent* e) override; - private: void Create(); GtkWidget* window_; @@ -75,16 +75,15 @@ class GTKWindow : public Window { bool closing_ = false; bool fullscreen_ = false; - }; class GTKMenuItem : public MenuItem { public: GTKMenuItem(Type type, const std::wstring& text, const std::wstring& hotkey, - std::function callback); + std::function callback); ~GTKMenuItem() override; - GtkWidget* handle() {return menu_;} + GtkWidget* handle() { return menu_; } using MenuItem::OnSelected; protected: