Massive refactoring of xenia::ui and GL swap behavior.

This seems to dramatically improve most games (especially with
--vsync=false), though it may cause swap issues with others.
New code should be easier to port, and enables elemental-forms to be
drawn for any emulator UI.
This commit is contained in:
Ben Vanik
2015-07-12 22:03:47 -07:00
parent e69c7b00a8
commit 15c17459be
61 changed files with 1994 additions and 2623 deletions

View File

@@ -27,7 +27,10 @@ Application* Application::current() {
return current_application_;
}
Application::Application() { current_application_ = this; }
Application::Application() {
current_application_ = this;
loop_ = xe::ui::Loop::Create();
}
Application::~Application() {
assert_true(current_application_ == this);
@@ -65,7 +68,7 @@ bool Application::Initialize() {
}
void Application::Quit() {
loop_.Quit();
loop_->Quit();
// TODO(benvanik): proper exit.
XELOGI("User-initiated death!");

View File

@@ -12,7 +12,7 @@
#include <memory>
#include "xenia/ui/platform.h"
#include "xenia/ui/loop.h"
namespace xe {
namespace debug {
@@ -27,7 +27,7 @@ class Application {
static std::unique_ptr<Application> Create();
static Application* current();
xe::ui::Loop* loop() { return &loop_; }
xe::ui::Loop* loop() { return loop_.get(); }
MainWindow* main_window() const { return main_window_.get(); }
void Quit();
@@ -37,7 +37,7 @@ class Application {
bool Initialize();
xe::ui::PlatformLoop loop_;
std::unique_ptr<xe::ui::Loop> loop_;
std::unique_ptr<MainWindow> main_window_;
};

View File

@@ -15,51 +15,46 @@
#include "xenia/base/logging.h"
#include "xenia/base/platform.h"
#include "xenia/base/threading.h"
// TODO(benvanik): platform based.
#include "xenia/ui/gl/wgl_elemental_control.h"
#include "xenia/ui/gl/gl_context.h"
namespace xe {
namespace debug {
namespace ui {
using xe::ui::MenuItem;
using xe::ui::PlatformMenu;
using xe::ui::PlatformWindow;
enum Commands {
IDC_FILE_EXIT,
IDC_HELP_WEBSITE,
IDC_HELP_ABOUT,
};
const std::wstring kBaseTitle = L"xenia debugger";
MainWindow::MainWindow(Application* app)
: PlatformWindow(app->loop(), kBaseTitle),
app_(app),
main_menu_(MenuItem::Type::kNormal) {}
MainWindow::MainWindow(Application* app) : app_(app) {}
// main_menu_(MenuItem::Type::kNormal) {}
MainWindow::~MainWindow() = default;
bool MainWindow::Initialize() {
if (!PlatformWindow::Initialize()) {
platform_window_ = xe::ui::Window::Create(app()->loop(), kBaseTitle);
if (!platform_window_) {
return false;
}
platform_window_->Initialize();
platform_window_->set_context(
xe::ui::gl::GLContext::Create(platform_window_.get()));
platform_window_->MakeReady();
on_key_down.AddListener([this](xe::ui::KeyEvent& e) {
platform_window_->on_closed.AddListener(
std::bind(&MainWindow::OnClose, this));
platform_window_->on_key_down.AddListener([this](xe::ui::KeyEvent& e) {
bool handled = true;
switch (e.key_code()) {
case 0x1B: { // VK_ESCAPE
// Allow users to escape fullscreen (but not enter it).
if (is_fullscreen()) {
ToggleFullscreen(false);
if (platform_window_->is_fullscreen()) {
platform_window_->ToggleFullscreen(false);
}
} break;
case 0x70: { // VK_F1
OnCommand(Commands::IDC_HELP_WEBSITE);
LaunchBrowser("http://xenia.jp");
} break;
default: { handled = false; } break;
@@ -68,35 +63,30 @@ bool MainWindow::Initialize() {
});
// Main menu.
auto file_menu =
std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&File");
auto main_menu = MenuItem::Create(MenuItem::Type::kNormal);
auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File");
{
file_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_FILE_EXIT, L"E&xit", L"Alt+F4"));
file_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, L"E&xit", L"Alt+F4",
[this]() { platform_window_->Close(); }));
}
main_menu_.AddChild(std::move(file_menu));
main_menu->AddChild(std::move(file_menu));
// Help menu.
auto help_menu =
std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&Help");
auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Help");
{
help_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_HELP_WEBSITE, L"&Website...",
L"F1"));
help_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_HELP_ABOUT, L"&About..."));
help_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, L"&Website...", L"F1",
[]() { LaunchBrowser("http://xenia.jp"); }));
help_menu->AddChild(
MenuItem::Create(MenuItem::Type::kString, L"&About...",
[]() { LaunchBrowser("http://xenia.jp/about/"); }));
}
main_menu_.AddChild(std::move(help_menu));
main_menu->AddChild(std::move(help_menu));
set_menu(&main_menu_);
platform_window_->set_main_menu(std::move(main_menu));
// 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.
control_ = std::make_unique<xe::ui::gl::WGLElementalControl>(loop());
AddChild(control_.get());
Resize(1440, 1200);
platform_window_->Resize(1440, 1200);
BuildUI();
@@ -107,7 +97,7 @@ void MainWindow::BuildUI() {
using namespace el::dsl;
el::AnimationBlocker animation_blocker;
auto root_element = control_->root_element();
auto root_element = platform_window_->root_element();
window_ = std::make_unique<el::Window>();
window_->set_settings(el::WindowSettings::kFullScreen);
root_element->AddChild(window_.get());
@@ -154,21 +144,6 @@ void MainWindow::BuildUI() {
void MainWindow::OnClose() { app_->Quit(); }
void MainWindow::OnCommand(int id) {
switch (id) {
case IDC_FILE_EXIT: {
Close();
} break;
case IDC_HELP_WEBSITE: {
LaunchBrowser("http://xenia.jp");
} break;
case IDC_HELP_ABOUT: {
LaunchBrowser("http://xenia.jp/about/");
} break;
}
}
} // namespace ui
} // namespace debug
} // namespace xe

View File

@@ -16,18 +16,16 @@
#include "xenia/debug/ui/application.h"
#include "xenia/debug/ui/views/cpu/cpu_view.h"
#include "xenia/debug/ui/views/gpu/gpu_view.h"
#include "xenia/ui/elemental_control.h"
#include "xenia/ui/platform.h"
#include "xenia/ui/window.h"
namespace xe {
namespace debug {
namespace ui {
class MainWindow : public xe::ui::PlatformWindow {
class MainWindow {
public:
MainWindow(Application* app);
~MainWindow() override;
~MainWindow();
Application* app() const { return app_; }
@@ -38,13 +36,11 @@ class MainWindow : public xe::ui::PlatformWindow {
private:
void BuildUI();
void OnClose() override;
void OnCommand(int id) override;
void OnClose();
Application* app_ = nullptr;
xe::ui::PlatformMenu main_menu_;
std::unique_ptr<xe::ui::ElementalControl> control_;
std::unique_ptr<xe::ui::Window> platform_window_;
std::unique_ptr<el::Window> window_;
struct {
el::SplitContainer* split_container;