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_