Commit 64d7d9c3 authored by James's avatar James
Browse files

Massive cleanup of initialisation/destruction of OpenGL resources

Includes cleanup of the LibRetro EmuWindow implementation

Fixes #40
parent 8c487e03
......@@ -118,12 +118,7 @@ uintptr_t LibRetro::GetFramebuffer() {
/**
* Updates Citra's settings with Libretro's.
*/
void UpdateSettings(bool init) {
// Check to see if we actually have any config updates to process.
if (!init && !LibRetro::HasUpdatedConfig()) {
return;
}
void UpdateSettings() {
struct retro_input_descriptor desc[] = {
{0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Left"},
{0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Up"},
......@@ -308,8 +303,8 @@ void UpdateSettings(bool init) {
}
}
// Update the framebuffer sizing, but only if there is a oGL context.
emu_instance->emu_window->Prepare(!init);
// Update the framebuffer sizing.
emu_instance->emu_window->UpdateLayout();
Settings::Apply();
}
......@@ -318,7 +313,10 @@ void UpdateSettings(bool init) {
* libretro callback; Called every game tick.
*/
void retro_run() {
UpdateSettings(false);
// Check to see if we actually have any config updates to process.
if (LibRetro::HasUpdatedConfig()) {
UpdateSettings();
}
// We can't assume that the frontend has been nice and preserved all OpenGL settings. Reset.
auto last_state = OpenGLState::GetCurState();
......@@ -387,14 +385,17 @@ void context_reset() {
LOG_ERROR(Render, "initialization failed!");
}
emu_instance->emu_window->Prepare(true);
emu_instance->emu_window->UpdateLayout();
emu_instance->emu_window->CreateContext();
}
void context_destroy() {
if (VideoCore::g_renderer != nullptr) {
VideoCore::g_renderer->ShutDown();
VideoCore::g_renderer = nullptr;
}
emu_instance->emu_window->DestroyContext();
VideoCore::g_renderer = nullptr;
}
void retro_reset() {
......@@ -433,8 +434,7 @@ bool retro_load_game(const struct retro_game_info* info) {
}
emu_instance->emu_window = std::make_unique<EmuWindow_LibRetro>();
UpdateSettings(true);
UpdateSettings();
const Core::System::ResultStatus load_result{Core::System::GetInstance().Load(
emu_instance->emu_window.get(), LibRetro::settings.file_path)};
......
......@@ -58,9 +58,8 @@ void EmuWindow_LibRetro::SwapBuffers() {
ResetGLState();
if (enableEmulatedPointer) {
// TODO: Port tracker to OpenGLState
tracker.Render(width, height);
if (tracker != nullptr) {
tracker->Render(width, height);
}
LibRetro::UploadVideoFrame(RETRO_HW_FRAME_BUFFER_VALID, static_cast<unsigned>(width),
......@@ -88,11 +87,11 @@ void EmuWindow_LibRetro::PollEvents() {
// TODO: Poll for right click for motion emu
if (enableEmulatedPointer) {
tracker.Update(width, height, GetFramebufferLayout().bottom_screen);
if (tracker != nullptr) {
tracker->Update(width, height, GetFramebufferLayout().bottom_screen);
if (tracker.IsPressed()) {
auto mousePos = tracker.GetPressedPosition();
if (tracker->IsPressed()) {
auto mousePos = tracker->GetPressedPosition();
if (hasTouched) {
TouchMoved(mousePos.first, mousePos.second);
......@@ -121,7 +120,7 @@ void EmuWindow_LibRetro::OnMinimalClientAreaChangeRequest(
height = minimal_size.second;
}
void EmuWindow_LibRetro::Prepare(bool hasOGL) {
void EmuWindow_LibRetro::UpdateLayout() {
// TODO: Handle custom layouts
// TODO: Extract this ugly thing somewhere else
unsigned baseX;
......@@ -200,17 +199,6 @@ void EmuWindow_LibRetro::Prepare(bool hasOGL) {
NotifyClientAreaSizeChanged(std::pair<unsigned, unsigned>(baseX, baseY));
OnMinimalClientAreaChangeRequest(std::pair<unsigned, unsigned>(baseX, baseY));
UpdateCurrentFramebufferLayout(baseX, baseY);
if (hasOGL) {
framebuffer = static_cast<GLuint>(LibRetro::GetFramebuffer());
if (enableEmulatedPointer) {
// TODO: This is potentially leaking OpenGL resources!
tracker.InitOpenGL();
}
doCleanFrame = true;
}
}
bool EmuWindow_LibRetro::ShouldDeferRendererInit() const {
......@@ -228,3 +216,17 @@ bool EmuWindow_LibRetro::HasSubmittedFrame() {
submittedFrame = false;
return state;
}
void EmuWindow_LibRetro::CreateContext() {
framebuffer = static_cast<GLuint>(LibRetro::GetFramebuffer());
if (enableEmulatedPointer) {
tracker = std::make_unique<LibRetro::Input::MouseTracker>();
}
doCleanFrame = true;
}
void EmuWindow_LibRetro::DestroyContext() {
tracker = nullptr;
}
......@@ -34,7 +34,7 @@ public:
void SetupFramebuffer() override;
/// Prepares the window for rendering
void Prepare(bool hasOGL);
void UpdateLayout();
/// Enables for deferring a renderer's initalisation.
bool ShouldDeferRendererInit() const override;
......@@ -45,6 +45,12 @@ public:
/// Flags that the framebuffer should be cleared.
bool NeedsClearing() const override;
/// Creates state for a currently running OpenGL context.
void CreateContext();
/// Destroys a currently running OpenGL context.
void DestroyContext();
private:
/// Called when a configuration change affects the minimal size of the window
void OnMinimalClientAreaChangeRequest(
......@@ -65,7 +71,7 @@ private:
GLuint framebuffer;
// For tracking mouse cursor
LibRetro::Input::MouseTracker tracker;
std::unique_ptr<LibRetro::Input::MouseTracker> tracker = nullptr;
bool enableEmulatedPointer = true;
};
......@@ -16,7 +16,7 @@ namespace LibRetro {
namespace Input {
void MouseTracker::InitOpenGL() {
MouseTracker::MouseTracker() {
// Could potentially also use Citra's built-in shaders, if they can be
// wrangled to cooperate.
const GLchar* vertex = R"(
......@@ -41,11 +41,11 @@ void MouseTracker::InitOpenGL() {
}
)";
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
vao.Create();
vbo.Create();
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindVertexArray(vao.handle);
glBindBuffer(GL_ARRAY_BUFFER, vbo.handle);
shader.Create(vertex, fragment);
......@@ -55,6 +55,12 @@ void MouseTracker::InitOpenGL() {
glVertexAttribPointer(positionVariable, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
MouseTracker::~MouseTracker() {
shader.Release();
vao.Release();
vbo.Release();
}
void MouseTracker::OnMouseMove(int deltaX, int deltaY) {
x += deltaX;
y += deltaY;
......@@ -165,7 +171,7 @@ void MouseTracker::Render(int bufferWidth, int bufferHeight) {
glUseProgram(shader.handle);
glBindVertexArray(vao);
glBindVertexArray(vao.handle);
// clang-format off
GLfloat cursor[] = {
......@@ -192,7 +198,7 @@ void MouseTracker::Render(int bufferWidth, int bufferHeight) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo.handle);
glBufferData(GL_ARRAY_BUFFER, sizeof(cursor), cursor, GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, 12);
......
......@@ -16,8 +16,8 @@ namespace Input {
/// for a touch-screen device.
class MouseTracker {
public:
/// Initalises OpenGL.
void InitOpenGL();
MouseTracker();
~MouseTracker();
/// Called whenever a mouse moves.
void OnMouseMove(int xDelta, int yDelta);
......@@ -56,8 +56,8 @@ private:
bool isPressed;
OGLProgram shader;
GLuint vbo;
GLuint vao;
OGLVertexArray vao;
OGLBuffer vbo;
MathUtil::Rectangle<unsigned> bottomScreen;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment