Moving graphics context creation around to hide actual creation.
Makes it easier to support APIs that don't have a concept of sharing.
This commit is contained in:
parent
d8fa54ffc4
commit
6c95ca1cdb
|
@ -31,7 +31,7 @@
|
||||||
#include "xenia/gpu/graphics_system.h"
|
#include "xenia/gpu/graphics_system.h"
|
||||||
#include "xenia/kernel/xmodule.h"
|
#include "xenia/kernel/xmodule.h"
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
#include "xenia/ui/gl/gl_context.h"
|
#include "xenia/ui/graphics_provider.h"
|
||||||
#include "xenia/ui/imgui_drawer.h"
|
#include "xenia/ui/imgui_drawer.h"
|
||||||
|
|
||||||
DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.");
|
DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.");
|
||||||
|
@ -108,16 +108,9 @@ bool DebugWindow::Initialize() {
|
||||||
|
|
||||||
window_->Resize(1500, 1000);
|
window_->Resize(1500, 1000);
|
||||||
|
|
||||||
// If there exists a display window we need to share resources with it.
|
// Create the graphics context used for drawing.
|
||||||
xe::ui::gl::GLContext* parent_context = nullptr;
|
auto provider = emulator_->display_window()->context()->provider();
|
||||||
if (emulator_->display_window()) {
|
window_->set_context(provider->CreateContext(window_.get()));
|
||||||
parent_context = reinterpret_cast<xe::ui::gl::GLContext*>(
|
|
||||||
emulator_->display_window()->context());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the GL context used for drawing.
|
|
||||||
auto context = xe::ui::gl::GLContext::Create(window_.get(), parent_context);
|
|
||||||
window_->set_context(std::move(context));
|
|
||||||
|
|
||||||
// Setup ImGui.
|
// Setup ImGui.
|
||||||
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window_.get());
|
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window_.get());
|
||||||
|
@ -133,8 +126,6 @@ bool DebugWindow::Initialize() {
|
||||||
|
|
||||||
void DebugWindow::DrawFrame() {
|
void DebugWindow::DrawFrame() {
|
||||||
xe::ui::GraphicsContextLock lock(window_->context());
|
xe::ui::GraphicsContextLock lock(window_->context());
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
auto current_tick_count = Clock::QueryHostTickCount();
|
auto current_tick_count = Clock::QueryHostTickCount();
|
||||||
|
@ -310,7 +301,8 @@ void DebugWindow::DrawToolbar() {
|
||||||
if (thread_info == state_.thread_info) {
|
if (thread_info == state_.thread_info) {
|
||||||
current_thread_index = i;
|
current_thread_index = i;
|
||||||
}
|
}
|
||||||
thread_combo.Append(thread_info->thread->name());
|
thread_combo.Append(thread_info->thread ? thread_info->thread->name()
|
||||||
|
: "(zombie)");
|
||||||
thread_combo.Append(static_cast<char>(0));
|
thread_combo.Append(static_cast<char>(0));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@ -1021,6 +1013,7 @@ void DebugWindow::DrawThreadsPane() {
|
||||||
auto thread_info = cache_.thread_execution_infos[i];
|
auto thread_info = cache_.thread_execution_infos[i];
|
||||||
auto thread = thread_info->thread;
|
auto thread = thread_info->thread;
|
||||||
bool is_current_thread = thread == state_.thread;
|
bool is_current_thread = thread == state_.thread;
|
||||||
|
assert_not_null(thread); // TODO(benvanik): zombie thread states.
|
||||||
if (is_current_thread && state_.has_changed_thread) {
|
if (is_current_thread && state_.has_changed_thread) {
|
||||||
ImGui::SetScrollHere();
|
ImGui::SetScrollHere();
|
||||||
state_.has_changed_thread = false;
|
state_.has_changed_thread = false;
|
||||||
|
|
|
@ -131,10 +131,6 @@ X_STATUS Emulator::Setup(
|
||||||
if (!graphics_system_) {
|
if (!graphics_system_) {
|
||||||
return X_STATUS_NOT_IMPLEMENTED;
|
return X_STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
display_window_->loop()->PostSynchronous([this]() {
|
|
||||||
display_window_->set_context(
|
|
||||||
graphics_system_->CreateContext(display_window_));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize the HID.
|
// Initialize the HID.
|
||||||
input_system_ = std::make_unique<xe::hid::InputSystem>(display_window_);
|
input_system_ = std::make_unique<xe::hid::InputSystem>(display_window_);
|
||||||
|
|
|
@ -18,27 +18,23 @@
|
||||||
#include "xenia/gpu/gl4/gl4_command_processor.h"
|
#include "xenia/gpu/gl4/gl4_command_processor.h"
|
||||||
#include "xenia/gpu/gl4/gl4_gpu_flags.h"
|
#include "xenia/gpu/gl4/gl4_gpu_flags.h"
|
||||||
#include "xenia/gpu/gpu_flags.h"
|
#include "xenia/gpu/gpu_flags.h"
|
||||||
|
#include "xenia/ui/gl/gl_provider.h"
|
||||||
#include "xenia/ui/window.h"
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace gpu {
|
namespace gpu {
|
||||||
namespace gl4 {
|
namespace gl4 {
|
||||||
|
|
||||||
std::unique_ptr<ui::GraphicsContext> GL4GraphicsSystem::CreateContext(
|
GL4GraphicsSystem::GL4GraphicsSystem() = default;
|
||||||
ui::Window* target_window) {
|
|
||||||
// Setup the GL control that actually does the drawing.
|
|
||||||
// We run here in the loop and only touch it (and its context) on this
|
|
||||||
// thread. That means some sync-fu when we want to swap.
|
|
||||||
return xe::ui::gl::GLContext::Create(target_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
GL4GraphicsSystem::GL4GraphicsSystem() : GraphicsSystem() {}
|
|
||||||
|
|
||||||
GL4GraphicsSystem::~GL4GraphicsSystem() = default;
|
GL4GraphicsSystem::~GL4GraphicsSystem() = default;
|
||||||
|
|
||||||
X_STATUS GL4GraphicsSystem::Setup(cpu::Processor* processor,
|
X_STATUS GL4GraphicsSystem::Setup(cpu::Processor* processor,
|
||||||
kernel::KernelState* kernel_state,
|
kernel::KernelState* kernel_state,
|
||||||
ui::Window* target_window) {
|
ui::Window* target_window) {
|
||||||
|
// Must create the provider so we can create contexts.
|
||||||
|
provider_ = xe::ui::gl::GLProvider::Create(target_window);
|
||||||
|
|
||||||
auto result = GraphicsSystem::Setup(processor, kernel_state, target_window);
|
auto result = GraphicsSystem::Setup(processor, kernel_state, target_window);
|
||||||
if (result) {
|
if (result) {
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -24,9 +24,6 @@ class GL4GraphicsSystem : public GraphicsSystem {
|
||||||
GL4GraphicsSystem();
|
GL4GraphicsSystem();
|
||||||
~GL4GraphicsSystem() override;
|
~GL4GraphicsSystem() override;
|
||||||
|
|
||||||
std::unique_ptr<ui::GraphicsContext> CreateContext(
|
|
||||||
ui::Window* target_window) override;
|
|
||||||
|
|
||||||
X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state,
|
X_STATUS Setup(cpu::Processor* processor, kernel::KernelState* kernel_state,
|
||||||
ui::Window* target_window) override;
|
ui::Window* target_window) override;
|
||||||
void Shutdown() override;
|
void Shutdown() override;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "xenia/base/threading.h"
|
#include "xenia/base/threading.h"
|
||||||
#include "xenia/gpu/command_processor.h"
|
#include "xenia/gpu/command_processor.h"
|
||||||
#include "xenia/gpu/gpu_flags.h"
|
#include "xenia/gpu/gpu_flags.h"
|
||||||
|
#include "xenia/ui/graphics_provider.h"
|
||||||
#include "xenia/ui/loop.h"
|
#include "xenia/ui/loop.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -33,14 +34,18 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor,
|
||||||
kernel_state_ = kernel_state;
|
kernel_state_ = kernel_state;
|
||||||
target_window_ = target_window;
|
target_window_ = target_window;
|
||||||
|
|
||||||
// Initialize rendering context.
|
// Initialize display and rendering context.
|
||||||
// This must happen on the UI thread.
|
// This must happen on the UI thread.
|
||||||
std::unique_ptr<xe::ui::GraphicsContext> processor_context;
|
std::unique_ptr<xe::ui::GraphicsContext> processor_context;
|
||||||
target_window_->loop()->PostSynchronous([&]() {
|
target_window_->loop()->PostSynchronous([&]() {
|
||||||
|
// Create the context used for presentation.
|
||||||
|
assert_null(target_window->context());
|
||||||
|
target_window_->set_context(provider_->CreateContext(target_window_));
|
||||||
|
|
||||||
// Setup the GL context the command processor will do all its drawing in.
|
// Setup the GL context the command processor will do all its drawing in.
|
||||||
// It's shared with the display context so that we can resolve framebuffers
|
// It's shared with the display context so that we can resolve framebuffers
|
||||||
// from it.
|
// from it.
|
||||||
processor_context = target_window->context()->CreateShared();
|
processor_context = provider()->CreateOffscreenContext();
|
||||||
processor_context->ClearCurrent();
|
processor_context->ClearCurrent();
|
||||||
});
|
});
|
||||||
if (!processor_context) {
|
if (!processor_context) {
|
||||||
|
|
|
@ -34,12 +34,10 @@ class GraphicsSystem {
|
||||||
public:
|
public:
|
||||||
virtual ~GraphicsSystem();
|
virtual ~GraphicsSystem();
|
||||||
|
|
||||||
virtual std::unique_ptr<ui::GraphicsContext> CreateContext(
|
|
||||||
ui::Window* target_window) = 0;
|
|
||||||
|
|
||||||
Memory* memory() const { return memory_; }
|
Memory* memory() const { return memory_; }
|
||||||
cpu::Processor* processor() const { return processor_; }
|
cpu::Processor* processor() const { return processor_; }
|
||||||
kernel::KernelState* kernel_state() const { return kernel_state_; }
|
kernel::KernelState* kernel_state() const { return kernel_state_; }
|
||||||
|
ui::GraphicsProvider* provider() const { return provider_.get(); }
|
||||||
|
|
||||||
virtual X_STATUS Setup(cpu::Processor* processor,
|
virtual X_STATUS Setup(cpu::Processor* processor,
|
||||||
kernel::KernelState* kernel_state,
|
kernel::KernelState* kernel_state,
|
||||||
|
@ -82,6 +80,7 @@ class GraphicsSystem {
|
||||||
cpu::Processor* processor_ = nullptr;
|
cpu::Processor* processor_ = nullptr;
|
||||||
kernel::KernelState* kernel_state_ = nullptr;
|
kernel::KernelState* kernel_state_ = nullptr;
|
||||||
ui::Window* target_window_ = nullptr;
|
ui::Window* target_window_ = nullptr;
|
||||||
|
std::unique_ptr<ui::GraphicsProvider> provider_;
|
||||||
|
|
||||||
uint32_t interrupt_callback_ = 0;
|
uint32_t interrupt_callback_ = 0;
|
||||||
uint32_t interrupt_callback_data_ = 0;
|
uint32_t interrupt_callback_data_ = 0;
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "xenia/base/platform_win.h"
|
#include "xenia/base/platform_win.h"
|
||||||
#include "xenia/base/threading.h"
|
#include "xenia/base/threading.h"
|
||||||
#include "xenia/hid/input_system.h"
|
#include "xenia/hid/input_system.h"
|
||||||
#include "xenia/ui/gl/gl_context.h"
|
#include "xenia/ui/gl/gl_provider.h"
|
||||||
#include "xenia/ui/imgui_drawer.h"
|
#include "xenia/ui/imgui_drawer.h"
|
||||||
#include "xenia/ui/window.h"
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
|
@ -67,9 +67,9 @@ std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
|
||||||
return drivers;
|
return drivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<xe::ui::GraphicsContext> CreateDemoContext(
|
std::unique_ptr<xe::ui::GraphicsProvider> CreateDemoGraphicsProvider(
|
||||||
xe::ui::Window* window) {
|
xe::ui::Window* window) {
|
||||||
return xe::ui::gl::GLContext::Create(window);
|
return xe::ui::gl::GLProvider::Create(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawInputStatus();
|
void DrawInputStatus();
|
||||||
|
@ -97,12 +97,13 @@ int hid_demo_main(const std::vector<std::wstring>& args) {
|
||||||
window->Resize(600, 500);
|
window->Resize(600, 500);
|
||||||
|
|
||||||
// Create the graphics context used for drawing and setup the window.
|
// Create the graphics context used for drawing and setup the window.
|
||||||
loop->PostSynchronous([&window]() {
|
std::unique_ptr<xe::ui::GraphicsProvider> graphics_provider;
|
||||||
|
loop->PostSynchronous([&window, &graphics_provider]() {
|
||||||
// Create context and give it to the window.
|
// Create context and give it to the window.
|
||||||
// The window will finish initialization wtih the context (loading
|
// The window will finish initialization wtih the context (loading
|
||||||
// resources, etc).
|
// resources, etc).
|
||||||
auto context = CreateDemoContext(window.get());
|
graphics_provider = CreateDemoGraphicsProvider(window.get());
|
||||||
window->set_context(std::move(context));
|
window->set_context(graphics_provider->CreateContext(window.get()));
|
||||||
|
|
||||||
// Initialize the ImGui renderer we'll use.
|
// Initialize the ImGui renderer we'll use.
|
||||||
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window.get());
|
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window.get());
|
||||||
|
@ -157,6 +158,7 @@ int hid_demo_main(const std::vector<std::wstring>& args) {
|
||||||
imgui_drawer_.reset();
|
imgui_drawer_.reset();
|
||||||
input_system_.reset();
|
input_system_.reset();
|
||||||
|
|
||||||
|
loop->PostSynchronous([&graphics_provider]() { graphics_provider.reset(); });
|
||||||
window.reset();
|
window.reset();
|
||||||
loop.reset();
|
loop.reset();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -58,24 +58,20 @@ void FatalGLError(std::string error) {
|
||||||
"of supported GPUs.");
|
"of supported GPUs.");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GLContext> GLContext::Create(Window* target_window,
|
std::unique_ptr<GLContext> GLContext::Create(GraphicsProvider* provider,
|
||||||
|
Window* target_window,
|
||||||
GLContext* share_context) {
|
GLContext* share_context) {
|
||||||
auto context = std::unique_ptr<GLContext>(new GLContext(target_window));
|
auto context =
|
||||||
if (!context->Initialize(target_window, share_context)) {
|
std::unique_ptr<GLContext>(new GLContext(provider, target_window));
|
||||||
|
if (!context->Initialize(share_context)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
context->AssertExtensionsPresent();
|
context->AssertExtensionsPresent();
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLContext::GLContext(Window* target_window) : GraphicsContext(target_window) {
|
GLContext::GLContext(GraphicsProvider* provider, Window* target_window)
|
||||||
glew_context_.reset(new GLEWContext());
|
: GraphicsContext(provider, target_window) {
|
||||||
wglew_context_.reset(new WGLEWContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
GLContext::GLContext(Window* target_window, HGLRC glrc)
|
|
||||||
: GraphicsContext(target_window), glrc_(glrc) {
|
|
||||||
dc_ = GetDC(HWND(target_window_->native_handle()));
|
|
||||||
glew_context_.reset(new GLEWContext());
|
glew_context_.reset(new GLEWContext());
|
||||||
wglew_context_.reset(new WGLEWContext());
|
wglew_context_.reset(new WGLEWContext());
|
||||||
}
|
}
|
||||||
|
@ -93,8 +89,7 @@ GLContext::~GLContext() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLContext::Initialize(Window* target_window, GLContext* share_context) {
|
bool GLContext::Initialize(GLContext* share_context) {
|
||||||
target_window_ = target_window;
|
|
||||||
dc_ = GetDC(HWND(target_window_->native_handle()));
|
dc_ = GetDC(HWND(target_window_->native_handle()));
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pfd = {0};
|
PIXELFORMATDESCRIPTOR pfd = {0};
|
||||||
|
@ -193,12 +188,13 @@ bool GLContext::Initialize(Window* target_window, GLContext* share_context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GraphicsContext> GLContext::CreateShared() {
|
std::unique_ptr<GLContext> GLContext::CreateOffscreen(
|
||||||
assert_not_null(glrc_);
|
GraphicsProvider* provider, GLContext* parent_context) {
|
||||||
|
assert_not_null(parent_context->glrc_);
|
||||||
|
|
||||||
HGLRC new_glrc = nullptr;
|
HGLRC new_glrc = nullptr;
|
||||||
{
|
{
|
||||||
GraphicsContextLock context_lock(this);
|
GraphicsContextLock context_lock(parent_context);
|
||||||
|
|
||||||
int context_flags = 0;
|
int context_flags = 0;
|
||||||
if (FLAGS_gl_debug) {
|
if (FLAGS_gl_debug) {
|
||||||
|
@ -214,15 +210,19 @@ std::unique_ptr<GraphicsContext> GLContext::CreateShared() {
|
||||||
WGL_CONTEXT_PROFILE_MASK_ARB,
|
WGL_CONTEXT_PROFILE_MASK_ARB,
|
||||||
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||||
0};
|
0};
|
||||||
new_glrc = wglCreateContextAttribsARB(dc_, glrc_, attrib_list);
|
new_glrc = wglCreateContextAttribsARB(parent_context->dc_,
|
||||||
|
parent_context->glrc_, attrib_list);
|
||||||
if (!new_glrc) {
|
if (!new_glrc) {
|
||||||
FatalGLError("Could not create shared context.");
|
FatalGLError("Could not create shared context.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto new_context =
|
auto new_context = std::unique_ptr<GLContext>(
|
||||||
std::unique_ptr<GLContext>(new GLContext(target_window_, new_glrc));
|
new GLContext(provider, parent_context->target_window_));
|
||||||
|
new_context->glrc_ = new_glrc;
|
||||||
|
new_context->dc_ =
|
||||||
|
GetDC(HWND(parent_context->target_window_->native_handle()));
|
||||||
if (!new_context->MakeCurrent()) {
|
if (!new_context->MakeCurrent()) {
|
||||||
FatalGLError("Could not make new GL context current.");
|
FatalGLError("Could not make new GL context current.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -244,18 +244,16 @@ std::unique_ptr<GraphicsContext> GLContext::CreateShared() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupDebugging();
|
new_context->SetupDebugging();
|
||||||
|
|
||||||
if (!new_context->blitter_.Initialize()) {
|
if (!new_context->blitter_.Initialize()) {
|
||||||
FatalGLError("Unable to initialize blitter on shared context.");
|
FatalGLError("Unable to initialize blitter on shared context.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_context->immediate_drawer_ = std::make_unique<GLImmediateDrawer>(this);
|
|
||||||
|
|
||||||
new_context->ClearCurrent();
|
new_context->ClearCurrent();
|
||||||
|
|
||||||
return std::unique_ptr<GraphicsContext>(new_context.release());
|
return new_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLContext::AssertExtensionsPresent() {
|
void GLContext::AssertExtensionsPresent() {
|
||||||
|
|
|
@ -29,18 +29,14 @@ namespace ui {
|
||||||
namespace gl {
|
namespace gl {
|
||||||
|
|
||||||
class GLImmediateDrawer;
|
class GLImmediateDrawer;
|
||||||
|
class GLProvider;
|
||||||
|
|
||||||
class GLContext : public GraphicsContext {
|
class GLContext : public GraphicsContext {
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<GLContext> Create(Window* target_window,
|
|
||||||
GLContext* share_context = nullptr);
|
|
||||||
|
|
||||||
~GLContext() override;
|
~GLContext() override;
|
||||||
|
|
||||||
HDC dc() const { return dc_; }
|
HDC dc() const { return dc_; }
|
||||||
|
|
||||||
std::unique_ptr<GraphicsContext> CreateShared() override;
|
|
||||||
|
|
||||||
ImmediateDrawer* immediate_drawer() override;
|
ImmediateDrawer* immediate_drawer() override;
|
||||||
|
|
||||||
bool is_current() override;
|
bool is_current() override;
|
||||||
|
@ -53,10 +49,18 @@ class GLContext : public GraphicsContext {
|
||||||
Blitter* blitter() { return &blitter_; }
|
Blitter* blitter() { return &blitter_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit GLContext(Window* target_window);
|
friend class GLProvider;
|
||||||
GLContext(Window* target_window, HGLRC glrc);
|
|
||||||
|
|
||||||
bool Initialize(Window* target_window, GLContext* share_context);
|
static std::unique_ptr<GLContext> Create(GraphicsProvider* provider,
|
||||||
|
Window* target_window,
|
||||||
|
GLContext* share_context = nullptr);
|
||||||
|
static std::unique_ptr<GLContext> CreateOffscreen(GraphicsProvider* provider,
|
||||||
|
GLContext* parent_context);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLContext(GraphicsProvider* provider, Window* target_window);
|
||||||
|
|
||||||
|
bool Initialize(GLContext* share_context);
|
||||||
void AssertExtensionsPresent();
|
void AssertExtensionsPresent();
|
||||||
|
|
||||||
void SetupDebugging();
|
void SetupDebugging();
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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/ui/gl/gl_provider.h"
|
||||||
|
|
||||||
|
#include "xenia/ui/gl/gl_context.h"
|
||||||
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace gl {
|
||||||
|
|
||||||
|
std::unique_ptr<GraphicsProvider> GLProvider::Create(Window* main_window) {
|
||||||
|
std::unique_ptr<GLProvider> provider(new GLProvider(main_window));
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
return std::unique_ptr<GraphicsProvider>(provider.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
GLProvider::GLProvider(Window* main_window) : GraphicsProvider(main_window) {}
|
||||||
|
|
||||||
|
GLProvider::~GLProvider() = default;
|
||||||
|
|
||||||
|
std::unique_ptr<GraphicsContext> GLProvider::CreateContext(
|
||||||
|
Window* target_window) {
|
||||||
|
auto share_context = main_window_->context();
|
||||||
|
return std::unique_ptr<GraphicsContext>(
|
||||||
|
GLContext::Create(this, target_window,
|
||||||
|
static_cast<GLContext*>(share_context))
|
||||||
|
.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GraphicsContext> GLProvider::CreateOffscreenContext() {
|
||||||
|
auto share_context = main_window_->context();
|
||||||
|
return std::unique_ptr<GraphicsContext>(
|
||||||
|
GLContext::CreateOffscreen(this, static_cast<GLContext*>(share_context))
|
||||||
|
.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace gl
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_UI_GL_GL_PROVIDER_H_
|
||||||
|
#define XENIA_UI_GL_GL_PROVIDER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "xenia/ui/graphics_provider.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
namespace gl {
|
||||||
|
|
||||||
|
class GLProvider : public GraphicsProvider {
|
||||||
|
public:
|
||||||
|
~GLProvider() override;
|
||||||
|
|
||||||
|
static std::unique_ptr<GraphicsProvider> Create(Window* main_window);
|
||||||
|
|
||||||
|
std::unique_ptr<GraphicsContext> CreateContext(
|
||||||
|
Window* target_window) override;
|
||||||
|
|
||||||
|
std::unique_ptr<GraphicsContext> CreateOffscreenContext() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit GLProvider(Window* main_window);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gl
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_UI_GL_GL_PROVIDER_H_
|
|
@ -11,7 +11,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/main.h"
|
#include "xenia/base/main.h"
|
||||||
#include "xenia/ui/gl/gl_context.h"
|
#include "xenia/ui/gl/gl_provider.h"
|
||||||
#include "xenia/ui/window.h"
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
@ -19,8 +19,8 @@ namespace ui {
|
||||||
|
|
||||||
int window_demo_main(const std::vector<std::wstring>& args);
|
int window_demo_main(const std::vector<std::wstring>& args);
|
||||||
|
|
||||||
std::unique_ptr<GraphicsContext> CreateDemoContext(Window* window) {
|
std::unique_ptr<GraphicsProvider> CreateDemoGraphicsProvider(Window* window) {
|
||||||
return xe::ui::gl::GLContext::Create(window);
|
return xe::ui::gl::GLProvider::Create(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ui
|
} // namespace ui
|
||||||
|
|
|
@ -9,11 +9,14 @@
|
||||||
|
|
||||||
#include "xenia/ui/graphics_context.h"
|
#include "xenia/ui/graphics_context.h"
|
||||||
|
|
||||||
|
#include "xenia/ui/graphics_provider.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
GraphicsContext::GraphicsContext(Window* target_window)
|
GraphicsContext::GraphicsContext(GraphicsProvider* provider,
|
||||||
: target_window_(target_window) {}
|
Window* target_window)
|
||||||
|
: provider_(provider), target_window_(target_window) {}
|
||||||
|
|
||||||
GraphicsContext::~GraphicsContext() = default;
|
GraphicsContext::~GraphicsContext() = default;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
|
class GraphicsProvider;
|
||||||
class ImmediateDrawer;
|
class ImmediateDrawer;
|
||||||
class Window;
|
class Window;
|
||||||
|
|
||||||
|
@ -22,9 +23,9 @@ class GraphicsContext {
|
||||||
public:
|
public:
|
||||||
virtual ~GraphicsContext();
|
virtual ~GraphicsContext();
|
||||||
|
|
||||||
|
GraphicsProvider* provider() const { return provider_; }
|
||||||
Window* target_window() const { return target_window_; }
|
Window* target_window() const { return target_window_; }
|
||||||
|
bool is_offscreen() { return immediate_drawer() == nullptr; }
|
||||||
virtual std::unique_ptr<GraphicsContext> CreateShared() = 0;
|
|
||||||
|
|
||||||
virtual ImmediateDrawer* immediate_drawer() = 0;
|
virtual ImmediateDrawer* immediate_drawer() = 0;
|
||||||
|
|
||||||
|
@ -36,8 +37,9 @@ class GraphicsContext {
|
||||||
virtual void EndSwap() = 0;
|
virtual void EndSwap() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit GraphicsContext(Window* target_window);
|
explicit GraphicsContext(GraphicsProvider* provider, Window* target_window);
|
||||||
|
|
||||||
|
GraphicsProvider* provider_ = nullptr;
|
||||||
Window* target_window_ = nullptr;
|
Window* target_window_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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_UI_GRAPHICS_PROVIDER_H_
|
||||||
|
#define XENIA_UI_GRAPHICS_PROVIDER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class GraphicsContext;
|
||||||
|
class Window;
|
||||||
|
|
||||||
|
// Factory for graphics contexts.
|
||||||
|
// All contexts created by the same provider will be able to share resources
|
||||||
|
// according to the rules of the backing graphics API.
|
||||||
|
class GraphicsProvider {
|
||||||
|
public:
|
||||||
|
virtual ~GraphicsProvider() = default;
|
||||||
|
|
||||||
|
// The 'main' window of an application, used to query provider information.
|
||||||
|
Window* main_window() const { return main_window_; }
|
||||||
|
|
||||||
|
// Creates a new graphics context and swapchain for presenting to a window.
|
||||||
|
virtual std::unique_ptr<GraphicsContext> CreateContext(
|
||||||
|
Window* target_window) = 0;
|
||||||
|
|
||||||
|
// Creates a new offscreen graphics context without a swapchain or immediate
|
||||||
|
// drawer.
|
||||||
|
virtual std::unique_ptr<GraphicsContext> CreateOffscreenContext() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit GraphicsProvider(Window* main_window) : main_window_(main_window) {}
|
||||||
|
|
||||||
|
Window* main_window_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ui
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_UI_GRAPHICS_PROVIDER_H_
|
|
@ -19,6 +19,7 @@
|
||||||
#include "xenia/base/platform_win.h"
|
#include "xenia/base/platform_win.h"
|
||||||
#include "xenia/base/profiling.h"
|
#include "xenia/base/profiling.h"
|
||||||
#include "xenia/base/threading.h"
|
#include "xenia/base/threading.h"
|
||||||
|
#include "xenia/ui/graphics_provider.h"
|
||||||
#include "xenia/ui/imgui_drawer.h"
|
#include "xenia/ui/imgui_drawer.h"
|
||||||
#include "xenia/ui/window.h"
|
#include "xenia/ui/window.h"
|
||||||
|
|
||||||
|
@ -26,9 +27,7 @@ namespace xe {
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
// Implemented in one of the window_*_demo.cc files under a subdir.
|
// Implemented in one of the window_*_demo.cc files under a subdir.
|
||||||
std::unique_ptr<GraphicsContext> CreateDemoContext(Window* window);
|
std::unique_ptr<GraphicsProvider> CreateDemoGraphicsProvider(Window* window);
|
||||||
|
|
||||||
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer_;
|
|
||||||
|
|
||||||
int window_demo_main(const std::vector<std::wstring>& args) {
|
int window_demo_main(const std::vector<std::wstring>& args) {
|
||||||
Profiler::Initialize();
|
Profiler::Initialize();
|
||||||
|
@ -45,13 +44,6 @@ int window_demo_main(const std::vector<std::wstring>& args) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
window->on_closed.AddListener([&loop](xe::ui::UIEvent* e) {
|
|
||||||
loop->Quit();
|
|
||||||
XELOGI("User-initiated death!");
|
|
||||||
imgui_drawer_.reset();
|
|
||||||
exit(1);
|
|
||||||
});
|
|
||||||
loop->on_quit.AddListener([&window](xe::ui::UIEvent* e) { window.reset(); });
|
|
||||||
|
|
||||||
// Main menu.
|
// Main menu.
|
||||||
auto main_menu = MenuItem::Create(MenuItem::Type::kNormal);
|
auto main_menu = MenuItem::Create(MenuItem::Type::kNormal);
|
||||||
|
@ -78,25 +70,37 @@ int window_demo_main(const std::vector<std::wstring>& args) {
|
||||||
window->Resize(1920, 1200);
|
window->Resize(1920, 1200);
|
||||||
|
|
||||||
// Create the graphics context used for drawing and setup the window.
|
// Create the graphics context used for drawing and setup the window.
|
||||||
loop->PostSynchronous([&window]() {
|
std::unique_ptr<GraphicsProvider> graphics_provider;
|
||||||
// Create context and give it to the window.
|
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer;
|
||||||
|
loop->PostSynchronous([&window, &graphics_provider, &imgui_drawer]() {
|
||||||
|
// Create graphics provider and an initial context for the window.
|
||||||
// The window will finish initialization wtih the context (loading
|
// The window will finish initialization wtih the context (loading
|
||||||
// resources, etc).
|
// resources, etc).
|
||||||
auto context = CreateDemoContext(window.get());
|
graphics_provider = CreateDemoGraphicsProvider(window.get());
|
||||||
window->set_context(std::move(context));
|
window->set_context(graphics_provider->CreateContext(window.get()));
|
||||||
|
|
||||||
// Setup the profiler display.
|
// Setup the profiler display.
|
||||||
GraphicsContextLock context_lock(window->context());
|
GraphicsContextLock context_lock(window->context());
|
||||||
Profiler::set_window(window.get());
|
Profiler::set_window(window.get());
|
||||||
|
|
||||||
// Initialize the ImGui renderer we'll use.
|
// Initialize the ImGui renderer we'll use.
|
||||||
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window.get());
|
imgui_drawer = std::make_unique<xe::ui::ImGuiDrawer>(window.get());
|
||||||
imgui_drawer_->SetupDefaultInput();
|
imgui_drawer->SetupDefaultInput();
|
||||||
|
|
||||||
// Show the elemental-forms debug UI so we can see it working.
|
// Show the elemental-forms debug UI so we can see it working.
|
||||||
el::util::ShowDebugInfoSettingsForm(window->root_element());
|
el::util::ShowDebugInfoSettingsForm(window->root_element());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window->on_closed.AddListener(
|
||||||
|
[&loop, &graphics_provider, &imgui_drawer](xe::ui::UIEvent* e) {
|
||||||
|
loop->Quit();
|
||||||
|
XELOGI("User-initiated death!");
|
||||||
|
imgui_drawer.reset();
|
||||||
|
graphics_provider.reset();
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
loop->on_quit.AddListener([&window](xe::ui::UIEvent* e) { window.reset(); });
|
||||||
|
|
||||||
window->on_key_down.AddListener([](xe::ui::KeyEvent* e) {
|
window->on_key_down.AddListener([](xe::ui::KeyEvent* e) {
|
||||||
switch (e->key_code()) {
|
switch (e->key_code()) {
|
||||||
case 0x72: { // F3
|
case 0x72: { // F3
|
||||||
|
@ -130,8 +134,9 @@ int window_demo_main(const std::vector<std::wstring>& args) {
|
||||||
// Wait until we are exited.
|
// Wait until we are exited.
|
||||||
loop->AwaitQuit();
|
loop->AwaitQuit();
|
||||||
|
|
||||||
imgui_drawer_.reset();
|
imgui_drawer.reset();
|
||||||
|
|
||||||
|
loop->PostSynchronous([&graphics_provider]() { graphics_provider.reset(); });
|
||||||
window.reset();
|
window.reset();
|
||||||
loop.reset();
|
loop.reset();
|
||||||
Profiler::Dump();
|
Profiler::Dump();
|
||||||
|
|
Loading…
Reference in New Issue