Implement GL context for windows platform

This commit is contained in:
Doug Johnson 2016-05-12 01:32:46 -06:00
parent ce10d9bd02
commit a63c9458cd
6 changed files with 810 additions and 8 deletions

View File

@ -56,6 +56,7 @@ void GLContext::FatalGLError(std::string error) {
GLContext::GLContext(GraphicsProvider* provider, Window* target_window) GLContext::GLContext(GraphicsProvider* provider, Window* target_window)
: GraphicsContext(provider, target_window) { } : GraphicsContext(provider, target_window) { }
GLContext::~GLContext() {}
void GLContext::AssertExtensionsPresent() { void GLContext::AssertExtensionsPresent() {
if (!MakeCurrent()) { if (!MakeCurrent()) {

View File

@ -21,9 +21,14 @@
DECLARE_bool(thread_safe_gl); DECLARE_bool(thread_safe_gl);
// TODO(benvanik): hide Win32 stuff. DECLARE_bool(disable_gl_context_reset);
typedef struct HDC__* HDC;
typedef struct HGLRC__* HGLRC; DECLARE_bool(random_clear_color);
DECLARE_bool(gl_debug);
DECLARE_bool(gl_debug_output);
DECLARE_bool(gl_debug_output_synchronous);
namespace xe { namespace xe {
namespace ui { namespace ui {
@ -38,13 +43,13 @@ class GLContext : public GraphicsContext {
ImmediateDrawer* immediate_drawer() override; ImmediateDrawer* immediate_drawer() override;
bool is_current() override; bool is_current() = 0;
bool MakeCurrent() override; bool MakeCurrent() = 0;
void ClearCurrent() override; void ClearCurrent() = 0;
bool WasLost() override; bool WasLost() override;
void BeginSwap() override; void BeginSwap() = 0;
void EndSwap() override; void EndSwap() = 0;
std::unique_ptr<RawImage> Capture() override; std::unique_ptr<RawImage> Capture() override;
Blitter* blitter() { return &blitter_; } Blitter* blitter() { return &blitter_; }

View File

@ -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 <gflags/gflags.h>
#include <mutex>
#include <string>
#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> GLContext::Create(GraphicsProvider* provider,
Window* target_window,
GLContext* share_context) {
auto context =
std::unique_ptr<GLContext>(new WGLContext(provider, target_window));
if (!context->Initialize(share_context)) {
return nullptr;
}
context->AssertExtensionsPresent();
return context;
}
std::unique_ptr<GLContext> GLContext::CreateOffscreen(
GraphicsProvider* provider, GLContext* parent_context) {
return WGLContext::CreateOffscreen(provider,
static_cast<WGLContext*>(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<WGLContext*>(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<GLImmediateDrawer>(this);
ClearCurrent();
return true;
}
std::unique_ptr<WGLContext> 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<WGLContext>(
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<float>(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

View File

@ -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 <gflags/gflags.h>
#include <memory>
#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<WGLContext> 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<GLEWContext> glew_context_;
std::unique_ptr<WGLEWContext> wglew_context_;
};
} // namespace gl
} // namespace ui
} // namespace xe
#endif // XENIA_UI_GL_GL_CONTEXT_H_

View File

@ -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 <gflags/gflags.h>
#include <mutex>
#include <string>
#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 <gdk/gdkx.h>
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> GLContext::Create(GraphicsProvider* provider,
Window* target_window,
GLContext* share_context) {
auto context =
std::unique_ptr<GLContext>(new GLXContext(provider, target_window));
if (!context->Initialize(share_context)) {
return nullptr;
}
context->AssertExtensionsPresent();
return context;
}
std::unique_ptr<GLContext> GLContext::CreateOffscreen(
GraphicsProvider* provider, GLContext* parent_context) {
return GLXContext::CreateOffscreen(provider,
dynamic_cast<GLXContext*>(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<GLXContext*>(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<GLImmediateDrawer>(this);
ClearCurrent();
return true;
}
std::unique_ptr<GLXContext> 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<GLXContext>(
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<float>(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

View File

@ -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 <gflags/gflags.h>
#include <memory>
#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<GLXContext> 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<GLEWContext> glew_context_;
std::unique_ptr<GLXEWContext> 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_