Commit a0c222c0 authored by James's avatar James
Browse files

Update for latest upstream

parent aea54fb1
......@@ -24,7 +24,7 @@ option(ENABLE_CUBEB "Enables the cubeb audio backend" OFF)
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
option(ENABLE_SCRIPTING "Enables scripting support" ON)
option(ENABLE_SCRIPTING "Enables scripting support" OFF)
option(DISABLE_CLANG_TARGET "Disables the Clang format check" ON)
......
......@@ -42,6 +42,8 @@ void DspInterface::OutputFrame(StereoFrame16& frame) {
return;
fifo.Push(frame.data(), frame.size());
GetSink().OnAudioSubmission(frame.size());
}
void DspInterface::OutputCallback(s16* buffer, std::size_t num_frames) {
......
......@@ -11,7 +11,11 @@
namespace AudioCore {
LibRetroSink::LibRetroSink(std::string target_device_name) {}
struct LibRetroSink::Impl {
std::function<void(s16*, std::size_t)> cb;
};
LibRetroSink::LibRetroSink(std::string target_device_name) : impl(std::make_unique<Impl>()) {}
LibRetroSink::~LibRetroSink() {}
......@@ -19,12 +23,16 @@ unsigned int LibRetroSink::GetNativeSampleRate() const {
return native_sample_rate; // We specify this.
}
void LibRetroSink::EnqueueSamples(const s16* samples, size_t sample_count) {
LibRetro::SubmitAudio(samples, sample_count);
void LibRetroSink::SetCallback(std::function<void(s16*, std::size_t)> cb) {
this->impl->cb = cb;
}
size_t LibRetroSink::SamplesInQueue() const {
return 0;
void LibRetroSink::OnAudioSubmission(std::size_t frames) {
std::vector<s16> buffer(frames * 2);
this->impl->cb(buffer.data(), buffer.size() / 2);
LibRetro::SubmitAudio(buffer.data(), buffer.size() / 2);
}
std::vector<std::string> ListLibretroSinkDevices() {
......
......@@ -26,9 +26,14 @@ public:
unsigned int GetNativeSampleRate() const override;
void EnqueueSamples(const s16* samples, size_t sample_count) override;
void SetCallback(std::function<void(s16*, std::size_t)> cb) override;
size_t SamplesInQueue() const override;
void OnAudioSubmission(std::size_t frames) override;
struct Impl;
private:
std::unique_ptr<Impl> impl;
};
void audio_callback();
......
......@@ -30,6 +30,9 @@ public:
* @param sample_count Number of samples.
*/
virtual void SetCallback(std::function<void(s16*, std::size_t)> cb) = 0;
/// Optional callback to signify that a buffer has been written.
virtual void OnAudioSubmission(std::size_t frames) {}
};
} // namespace AudioCore
......@@ -24,16 +24,16 @@ namespace AudioCore {
// g_sink_details is ordered in terms of desirability, with the best choice at the top.
const std::vector<SinkDetails> g_sink_details = {
#ifdef HAVE_LIBRETRO
SinkDetails{"libretro", &std::make_unique<LibRetroSink, std::string>, &ListLibretroSinkDevices},
SinkDetails{"libretro", &std::make_unique<LibRetroSink, std::string>, &ListLibretroSinkDevices, true},
#endif
#ifdef HAVE_CUBEB
SinkDetails{"cubeb", &std::make_unique<CubebSink, std::string>, &ListCubebSinkDevices},
SinkDetails{"cubeb", &std::make_unique<CubebSink, std::string>, &ListCubebSinkDevices, false},
#endif
#ifdef HAVE_SDL2
SinkDetails{"sdl2", &std::make_unique<SDL2Sink, std::string>, &ListSDL2SinkDevices},
SinkDetails{"sdl2", &std::make_unique<SDL2Sink, std::string>, &ListSDL2SinkDevices, false},
#endif
SinkDetails{"null", &std::make_unique<NullSink, std::string>,
[] { return std::vector<std::string>{"null"}; }},
[] { return std::vector<std::string>{"null"}; }, false},
};
const SinkDetails& GetSinkDetails(std::string_view sink_id) {
......
......@@ -19,8 +19,8 @@ struct SinkDetails {
using FactoryFn = std::function<std::unique_ptr<Sink>(std::string)>;
using ListDevicesFn = std::function<std::vector<std::string>()>;
SinkDetails(const char* id_, FactoryFn factory_, ListDevicesFn list_devices_)
: id(id_), factory(std::move(factory_)), list_devices(std::move(list_devices_)) {}
SinkDetails(const char* id_, FactoryFn factory_, ListDevicesFn list_devices_, bool is_sync_)
: id(id_), factory(std::move(factory_)), list_devices(std::move(list_devices_)), is_sync(is_sync_) {}
/// Name for this sink.
const char* id;
......@@ -28,6 +28,8 @@ struct SinkDetails {
FactoryFn factory;
/// A method to call to list available devices.
ListDevicesFn list_devices;
/// If this sink should be handled synchronously.
bool is_sync;
};
extern const std::vector<SinkDetails> g_sink_details;
......
......@@ -8,6 +8,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <common/file_util.h>
#include "glad/glad.h"
#include "libretro.h"
......@@ -308,8 +309,8 @@ void UpdateSettings() {
if (!FileUtil::CreateDir(target_dir)) {
LOG_ERROR(Frontend, "Failed to create \"{}\". Using Citra's default paths.", target_dir);
} else {
FileUtil::GetUserPath(D_ROOT_IDX, target_dir);
const auto& target_dir_result = FileUtil::GetUserPath(D_USER_IDX, target_dir);
FileUtil::GetUserPath(FileUtil::UserPath::RootDir, target_dir);
const auto& target_dir_result = FileUtil::GetUserPath(FileUtil::UserPath::UserDir, target_dir);
LOG_INFO(Frontend, "User dir set to \"{}\".", target_dir_result);
}
}
......@@ -346,9 +347,6 @@ void retro_run() {
case Core::System::ResultStatus::ErrorSystemFiles:
msg = "Citra was unable to locate a 3DS system archive: " + errorContent;
break;
case Core::System::ResultStatus::ErrorSharedFont:
msg = "Citra was unable to locate the 3DS shared fonts.";
break;
default:
msg = "Fatal Error encountered: " + errorContent;
break;
......@@ -389,9 +387,8 @@ void context_reset() {
"Likely memory leak: context_destroy() was not called before context_reset()!");
}
VideoCore::g_renderer = std::make_unique<RendererOpenGL>();
VideoCore::g_renderer->SetWindow(emu_instance->emu_window.get());
if (VideoCore::g_renderer->Init()) {
VideoCore::g_renderer = std::make_unique<RendererOpenGL>(*emu_instance->emu_window);
if (VideoCore::g_renderer->Init() != Core::System::ResultStatus::Success) {
LOG_DEBUG(Render, "initialized OK");
} else {
LOG_ERROR(Render, "initialization failed!");
......@@ -412,7 +409,7 @@ void context_destroy() {
void retro_reset() {
Core::System::GetInstance().Shutdown();
Core::System::GetInstance().Load(emu_instance->emu_window.get(), LibRetro::settings.file_path);
Core::System::GetInstance().Load(*emu_instance->emu_window, LibRetro::settings.file_path);
context_reset(); // Force the renderer to appear
}
......@@ -449,7 +446,7 @@ bool retro_load_game(const struct retro_game_info* info) {
UpdateSettings();
const Core::System::ResultStatus load_result{Core::System::GetInstance().Load(
emu_instance->emu_window.get(), LibRetro::settings.file_path)};
*emu_instance->emu_window, LibRetro::settings.file_path)};
switch (load_result) {
case Core::System::ResultStatus::ErrorGetLoader:
......
......@@ -52,6 +52,10 @@ bool SetAudioCallback(retro_audio_callback* cb) {
return environ_cb(RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK, cb);
}
bool SetFrameTimeCallback(retro_frame_time_callback* cb) {
return environ_cb(RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK, cb);
}
bool SetGeometry(retro_system_av_info* cb) {
return environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, cb);
}
......
......@@ -51,6 +51,9 @@ bool SetHWRenderer(retro_hw_render_callback* cb);
/// Sets the async audio callback.
bool SetAudioCallback(retro_audio_callback* cb);
/// Sets the frame time callback.
bool SetFrameTimeCallback(retro_frame_time_callback* cb);
/// Set the size of the new screen buffer.
bool SetGeometry(retro_system_av_info* cb);
......
......@@ -29,6 +29,38 @@ namespace Log {
*/
class Impl {
public:
Impl() {
backend_thread = std::thread([&] {
Entry entry;
auto write_logs = [&](Entry& e) {
std::lock_guard<std::mutex> lock(writing_mutex);
for (const auto& backend : backends) {
backend->Write(e);
}
};
while (true) {
std::unique_lock<std::mutex> lock(message_mutex);
message_cv.wait(lock, [&] { return !running || message_queue.Pop(entry); });
if (!running) {
break;
}
write_logs(entry);
}
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a case
// where a system is repeatedly spamming logs even on close.
constexpr int MAX_LOGS_TO_WRITE = 100;
int logs_written = 0;
while (logs_written++ < MAX_LOGS_TO_WRITE && message_queue.Pop(entry)) {
write_logs(entry);
}
});
}
~Impl() {
running = false;
message_cv.notify_one();
backend_thread.join();
}
Impl(Impl const&) = delete;
const Impl& operator=(Impl const&) = delete;
......@@ -70,39 +102,6 @@ public:
}
private:
Impl() {
backend_thread = std::thread([&] {
Entry entry;
auto write_logs = [&](Entry& e) {
std::lock_guard<std::mutex> lock(writing_mutex);
for (const auto& backend : backends) {
backend->Write(e);
}
};
while (true) {
std::unique_lock<std::mutex> lock(message_mutex);
message_cv.wait(lock, [&] { return !running || message_queue.Pop(entry); });
if (!running) {
break;
}
write_logs(entry);
}
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a case
// where a system is repeatedly spamming logs even on close.
constexpr int MAX_LOGS_TO_WRITE = 100;
int logs_written = 0;
while (logs_written++ < MAX_LOGS_TO_WRITE && message_queue.Pop(entry)) {
write_logs(entry);
}
});
}
~Impl() {
running = false;
message_cv.notify_one();
backend_thread.join();
}
std::atomic_bool running{true};
std::mutex message_mutex, writing_mutex;
std::condition_variable message_cv;
......
......@@ -103,7 +103,7 @@ void RendererOpenGL::SwapBuffers() {
OpenGLState prev_state = OpenGLState::GetCurState();
state.Apply();
render_window->SetupFramebuffer();
render_window.SetupFramebuffer();
for (int i : {0, 1, 2}) {
int fb_id = i == 2 ? 1 : 0;
......@@ -398,7 +398,7 @@ void RendererOpenGL::DrawScreens() {
glViewport(0, 0, layout.width, layout.height);
if (render_window->NeedsClearing()) {
if (render_window.NeedsClearing()) {
glClear(GL_COLOR_BUFFER_BIT);
}
......
......@@ -4,6 +4,7 @@
#include <memory>
#include "common/logging/log.h"
#include "core/frontend/emu_window.h"
#include "video_core/pica.h"
#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
......@@ -27,16 +28,21 @@ std::atomic<bool> g_renderer_bg_color_update_requested;
Core::System::ResultStatus Init(EmuWindow& emu_window) {
Pica::Init();
g_renderer = std::make_unique<RendererOpenGL>(emu_window);
Core::System::ResultStatus result = g_renderer->Init();
if (!emu_window.ShouldDeferRendererInit()) {
g_renderer = std::make_unique<RendererOpenGL>(emu_window);
Core::System::ResultStatus result = g_renderer->Init();
if (result != Core::System::ResultStatus::Success) {
LOG_ERROR(Render, "initialization failed !");
if (result != Core::System::ResultStatus::Success) {
LOG_ERROR(Render, "initialization failed !");
} else {
LOG_DEBUG(Render, "initialized OK");
}
return result;
} else {
LOG_DEBUG(Render, "initialized OK");
// We will come back to it later
return Core::System::ResultStatus::Success;
}
return result;
}
/// Shutdown the video core
......
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