mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 18:00:07 +00:00
implement custom texture preload
This commit is contained in:
parent
657a129b60
commit
59b475a4b9
@ -165,6 +165,8 @@ void Config::ReadValues() {
|
|||||||
// Utility
|
// Utility
|
||||||
Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false);
|
Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false);
|
||||||
Settings::values.custom_textures = sdl2_config->GetBoolean("Utility", "custom_textures", false);
|
Settings::values.custom_textures = sdl2_config->GetBoolean("Utility", "custom_textures", false);
|
||||||
|
Settings::values.preload_textures =
|
||||||
|
sdl2_config->GetBoolean("Utility", "preload_textures", false);
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false);
|
Settings::values.enable_dsp_lle = sdl2_config->GetBoolean("Audio", "enable_dsp_lle", false);
|
||||||
|
@ -186,6 +186,10 @@ dump_textures =
|
|||||||
# 0 (default): Off, 1: On
|
# 0 (default): Off, 1: On
|
||||||
custom_textures =
|
custom_textures =
|
||||||
|
|
||||||
|
# Loads all custom textures into memory before booting.
|
||||||
|
# 0 (default): Off, 1: On
|
||||||
|
preload_textures =
|
||||||
|
|
||||||
[Audio]
|
[Audio]
|
||||||
# Whether or not to enable DSP LLE
|
# Whether or not to enable DSP LLE
|
||||||
# 0 (default): No, 1: Yes
|
# 0 (default): No, 1: Yes
|
||||||
|
@ -17,8 +17,6 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
SetConfiguration();
|
SetConfiguration();
|
||||||
|
|
||||||
ui->layoutBox->setEnabled(!Settings::values.custom_layout);
|
|
||||||
|
|
||||||
ui->hw_renderer_group->setEnabled(ui->toggle_hw_renderer->isChecked());
|
ui->hw_renderer_group->setEnabled(ui->toggle_hw_renderer->isChecked());
|
||||||
connect(ui->toggle_hw_renderer, &QCheckBox::toggled, ui->hw_renderer_group,
|
connect(ui->toggle_hw_renderer, &QCheckBox::toggled, ui->hw_renderer_group,
|
||||||
&QWidget::setEnabled);
|
&QWidget::setEnabled);
|
||||||
@ -36,21 +34,6 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(ui->render_3d_combobox,
|
|
||||||
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
|
|
||||||
[this](int currentIndex) {
|
|
||||||
updateShaders(static_cast<Settings::StereoRenderOption>(currentIndex) ==
|
|
||||||
Settings::StereoRenderOption::Anaglyph);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(ui->bg_button, &QPushButton::clicked, this, [this] {
|
|
||||||
const QColor new_bg_color = QColorDialog::getColor(bg_color);
|
|
||||||
if (!new_bg_color.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UpdateBackgroundColorButton(new_bg_color);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigureGraphics::~ConfigureGraphics() = default;
|
ConfigureGraphics::~ConfigureGraphics() = default;
|
||||||
@ -60,15 +43,6 @@ void ConfigureGraphics::SetConfiguration() {
|
|||||||
ui->toggle_hw_shader->setChecked(Settings::values.use_hw_shader);
|
ui->toggle_hw_shader->setChecked(Settings::values.use_hw_shader);
|
||||||
ui->toggle_accurate_mul->setChecked(Settings::values.shaders_accurate_mul);
|
ui->toggle_accurate_mul->setChecked(Settings::values.shaders_accurate_mul);
|
||||||
ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit);
|
ui->toggle_shader_jit->setChecked(Settings::values.use_shader_jit);
|
||||||
ui->resolution_factor_combobox->setCurrentIndex(Settings::values.resolution_factor);
|
|
||||||
ui->render_3d_combobox->setCurrentIndex(static_cast<int>(Settings::values.render_3d));
|
|
||||||
ui->factor_3d->setValue(Settings::values.factor_3d);
|
|
||||||
updateShaders(Settings::values.render_3d == Settings::StereoRenderOption::Anaglyph);
|
|
||||||
ui->toggle_linear_filter->setChecked(Settings::values.filter_mode);
|
|
||||||
ui->layout_combobox->setCurrentIndex(static_cast<int>(Settings::values.layout_option));
|
|
||||||
ui->swap_screen->setChecked(Settings::values.swap_screen);
|
|
||||||
UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
|
|
||||||
Settings::values.bg_blue));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureGraphics::ApplyConfiguration() {
|
void ConfigureGraphics::ApplyConfiguration() {
|
||||||
@ -76,49 +50,6 @@ void ConfigureGraphics::ApplyConfiguration() {
|
|||||||
Settings::values.use_hw_shader = ui->toggle_hw_shader->isChecked();
|
Settings::values.use_hw_shader = ui->toggle_hw_shader->isChecked();
|
||||||
Settings::values.shaders_accurate_mul = ui->toggle_accurate_mul->isChecked();
|
Settings::values.shaders_accurate_mul = ui->toggle_accurate_mul->isChecked();
|
||||||
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
Settings::values.use_shader_jit = ui->toggle_shader_jit->isChecked();
|
||||||
Settings::values.resolution_factor =
|
|
||||||
static_cast<u16>(ui->resolution_factor_combobox->currentIndex());
|
|
||||||
Settings::values.render_3d =
|
|
||||||
static_cast<Settings::StereoRenderOption>(ui->render_3d_combobox->currentIndex());
|
|
||||||
Settings::values.factor_3d = ui->factor_3d->value();
|
|
||||||
Settings::values.pp_shader_name =
|
|
||||||
ui->shader_combobox->itemText(ui->shader_combobox->currentIndex()).toStdString();
|
|
||||||
Settings::values.filter_mode = ui->toggle_linear_filter->isChecked();
|
|
||||||
Settings::values.layout_option =
|
|
||||||
static_cast<Settings::LayoutOption>(ui->layout_combobox->currentIndex());
|
|
||||||
Settings::values.swap_screen = ui->swap_screen->isChecked();
|
|
||||||
Settings::values.dump_textures = ui->toggle_dump_textures->isChecked();
|
|
||||||
Settings::values.custom_textures = ui->toggle_custom_textures->isChecked();
|
|
||||||
Settings::values.bg_red = static_cast<float>(bg_color.redF());
|
|
||||||
Settings::values.bg_green = static_cast<float>(bg_color.greenF());
|
|
||||||
Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureGraphics::updateShaders(bool anaglyph) {
|
|
||||||
ui->shader_combobox->clear();
|
|
||||||
|
|
||||||
if (anaglyph)
|
|
||||||
ui->shader_combobox->addItem("dubois (builtin)");
|
|
||||||
else
|
|
||||||
ui->shader_combobox->addItem("none (builtin)");
|
|
||||||
|
|
||||||
ui->shader_combobox->setCurrentIndex(0);
|
|
||||||
|
|
||||||
for (const auto& shader : OpenGL::GetPostProcessingShaderList(anaglyph)) {
|
|
||||||
ui->shader_combobox->addItem(QString::fromStdString(shader));
|
|
||||||
if (Settings::values.pp_shader_name == shader)
|
|
||||||
ui->shader_combobox->setCurrentIndex(ui->shader_combobox->count() - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureGraphics::UpdateBackgroundColorButton(const QColor& color) {
|
|
||||||
bg_color = color;
|
|
||||||
|
|
||||||
QPixmap pixmap(ui->bg_button->size());
|
|
||||||
pixmap.fill(bg_color);
|
|
||||||
|
|
||||||
const QIcon color_icon(pixmap);
|
|
||||||
ui->bg_button->setIcon(color_icon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureGraphics::RetranslateUI() {
|
void ConfigureGraphics::RetranslateUI() {
|
||||||
|
@ -354,6 +354,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="toggle_preload_textures">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Load all custom textures into memory on boot, instead of loading them when the game requires them.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Preload Custom Textures</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -161,7 +161,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||||||
continue;
|
continue;
|
||||||
button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu);
|
button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
connect(button_map[button_id], &QPushButton::clicked, [=]() {
|
connect(button_map[button_id], &QPushButton::clicked, [=]() {
|
||||||
HandleClick(button_map[button_id],
|
HandleClick(
|
||||||
|
button_map[button_id],
|
||||||
[=](const Common::ParamPackage& params) {
|
[=](const Common::ParamPackage& params) {
|
||||||
buttons_param[button_id] = params;
|
buttons_param[button_id] = params;
|
||||||
// If the user closes the dialog, the changes are reverted in
|
// If the user closes the dialog, the changes are reverted in
|
||||||
@ -198,7 +199,8 @@ ConfigureInput::ConfigureInput(QWidget* parent)
|
|||||||
analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy(
|
analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy(
|
||||||
Qt::CustomContextMenu);
|
Qt::CustomContextMenu);
|
||||||
connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::clicked, [=]() {
|
connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::clicked, [=]() {
|
||||||
HandleClick(analog_map_buttons[analog_id][sub_button_id],
|
HandleClick(
|
||||||
|
analog_map_buttons[analog_id][sub_button_id],
|
||||||
[=](const Common::ParamPackage& params) {
|
[=](const Common::ParamPackage& params) {
|
||||||
SetAnalogButton(params, analogs_param[analog_id],
|
SetAnalogButton(params, analogs_param[analog_id],
|
||||||
analog_sub_buttons[sub_button_id]);
|
analog_sub_buttons[sub_button_id]);
|
||||||
|
@ -84,6 +84,8 @@ add_library(common STATIC
|
|||||||
swap.h
|
swap.h
|
||||||
telemetry.cpp
|
telemetry.cpp
|
||||||
telemetry.h
|
telemetry.h
|
||||||
|
texture.cpp
|
||||||
|
texture.h
|
||||||
thread.cpp
|
thread.cpp
|
||||||
thread.h
|
thread.h
|
||||||
thread_queue_list.h
|
thread_queue_list.h
|
||||||
|
@ -34,8 +34,7 @@ void DetachedTasks::AddTask(std::function<void()> task) {
|
|||||||
std::unique_lock lock{instance->mutex};
|
std::unique_lock lock{instance->mutex};
|
||||||
--instance->count;
|
--instance->count;
|
||||||
std::notify_all_at_thread_exit(instance->cv, std::move(lock));
|
std::notify_all_at_thread_exit(instance->cv, std::move(lock));
|
||||||
})
|
}).detach();
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
22
src/common/texture.cpp
Normal file
22
src/common/texture.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include <vector>
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
void FlipRGBA8Texture(std::vector<u8>& tex, u64 width, u64 height) {
|
||||||
|
ASSERT(tex.size() == width * height * 4);
|
||||||
|
const u64 line_size = width * 4;
|
||||||
|
u8* temp_row = new u8[line_size];
|
||||||
|
u32 offset_1;
|
||||||
|
u32 offset_2;
|
||||||
|
for (u64 line = 0; line < height / 2; line++) {
|
||||||
|
offset_1 = line * line_size;
|
||||||
|
offset_2 = (height - line - 1) * line_size;
|
||||||
|
// Swap lines
|
||||||
|
std::memcpy(temp_row, &tex[offset_1], line_size);
|
||||||
|
std::memcpy(&tex[offset_1], &tex[offset_2], line_size);
|
||||||
|
std::memcpy(&tex[offset_2], temp_row, line_size);
|
||||||
|
}
|
||||||
|
delete[] temp_row;
|
||||||
|
}
|
||||||
|
} // namespace Common
|
8
src/common/texture.h
Normal file
8
src/common/texture.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
void FlipRGBA8Texture(std::vector<u8>& tex, u64 width, u64 height);
|
||||||
|
}
|
@ -460,7 +460,7 @@ endif()
|
|||||||
create_target_directory_groups(core)
|
create_target_directory_groups(core)
|
||||||
|
|
||||||
target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core)
|
target_link_libraries(core PUBLIC common PRIVATE audio_core network video_core)
|
||||||
target_link_libraries(core PUBLIC Boost::boost PRIVATE cryptopp fmt open_source_archives)
|
target_link_libraries(core PUBLIC Boost::boost PRIVATE cryptopp fmt open_source_archives lodepng)
|
||||||
if (ENABLE_WEB_SERVICE)
|
if (ENABLE_WEB_SERVICE)
|
||||||
target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE)
|
target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE)
|
||||||
target_link_libraries(core PRIVATE web_service)
|
target_link_libraries(core PRIVATE web_service)
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <lodepng.h>
|
||||||
#include "audio_core/dsp_interface.h"
|
#include "audio_core/dsp_interface.h"
|
||||||
#include "audio_core/hle/hle.h"
|
#include "audio_core/hle/hle.h"
|
||||||
#include "audio_core/lle/lle.h"
|
#include "audio_core/lle/lle.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/texture.h"
|
||||||
#include "core/arm/arm_interface.h"
|
#include "core/arm/arm_interface.h"
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||||
@ -159,7 +161,52 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
|
|||||||
perf_stats = std::make_unique<PerfStats>(title_id);
|
perf_stats = std::make_unique<PerfStats>(title_id);
|
||||||
=======
|
=======
|
||||||
custom_tex_cache = std::make_unique<Core::CustomTexCache>();
|
custom_tex_cache = std::make_unique<Core::CustomTexCache>();
|
||||||
|
<<<<<<< HEAD
|
||||||
>>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory
|
>>>>>>> 387a49d7... fix crashes, add custom texture cache, load textures from load directory
|
||||||
|
=======
|
||||||
|
if (Settings::values.preload_textures) {
|
||||||
|
// Custom textures are currently stored as
|
||||||
|
// load/textures/[TitleID]/tex1_[width]x[height]_[64-bit hash]_[format].png
|
||||||
|
const std::string load_path =
|
||||||
|
fmt::format("{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
|
||||||
|
process->codeset->program_id);
|
||||||
|
|
||||||
|
if (FileUtil::Exists(load_path)) {
|
||||||
|
FileUtil::FSTEntry texture_files;
|
||||||
|
FileUtil::ScanDirectoryTree(load_path, texture_files);
|
||||||
|
for (const auto& file : texture_files.children) {
|
||||||
|
if (file.isDirectory)
|
||||||
|
continue;
|
||||||
|
if (file.virtualName.substr(0, 5) != "tex1_")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
u32 width;
|
||||||
|
u32 height;
|
||||||
|
u64 hash;
|
||||||
|
u32 format; // unused
|
||||||
|
// TODO: more modern way of doing this
|
||||||
|
if (std::sscanf(file.virtualName.c_str(), "tex1_%ux%u_%llX_%u.png", &width, &height,
|
||||||
|
&hash, &format) == 4) {
|
||||||
|
u32 png_width;
|
||||||
|
u32 png_height;
|
||||||
|
std::vector<u8> decoded_png;
|
||||||
|
|
||||||
|
u32 lodepng_ret =
|
||||||
|
lodepng::decode(decoded_png, png_width, png_height, file.physicalName);
|
||||||
|
if (lodepng_ret)
|
||||||
|
LOG_CRITICAL(Render_OpenGL, "Failed to preload custom texture: {}",
|
||||||
|
lodepng_error_text(lodepng_ret));
|
||||||
|
else {
|
||||||
|
LOG_INFO(Render_OpenGL, "Preloaded custom texture from {}",
|
||||||
|
file.physicalName);
|
||||||
|
Common::FlipRGBA8Texture(decoded_png, png_width, png_height);
|
||||||
|
custom_tex_cache->CacheTexture(hash, decoded_png, png_width, png_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
>>>>>>> 015582b2... implement custom texture preload
|
||||||
status = ResultStatus::Success;
|
status = ResultStatus::Success;
|
||||||
m_emu_window = &emu_window;
|
m_emu_window = &emu_window;
|
||||||
m_filepath = filepath;
|
m_filepath = filepath;
|
||||||
@ -195,8 +242,8 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, u32 system_mo
|
|||||||
|
|
||||||
timing = std::make_unique<Timing>();
|
timing = std::make_unique<Timing>();
|
||||||
|
|
||||||
kernel = std::make_unique<Kernel::KernelSystem>(*memory, *timing,
|
kernel = std::make_unique<Kernel::KernelSystem>(
|
||||||
[this] { PrepareReschedule(); }, system_mode);
|
*memory, *timing, [this] { PrepareReschedule(); }, system_mode);
|
||||||
|
|
||||||
if (Settings::values.use_cpu_jit) {
|
if (Settings::values.use_cpu_jit) {
|
||||||
#ifdef ARCHITECTURE_x86_64
|
#ifdef ARCHITECTURE_x86_64
|
||||||
|
@ -1340,7 +1340,8 @@ void Module::CheckAndUpdateFile(const CecDataPathType path_type, const u32 ncch_
|
|||||||
case CecDataPathType::MboxData:
|
case CecDataPathType::MboxData:
|
||||||
case CecDataPathType::MboxIcon:
|
case CecDataPathType::MboxIcon:
|
||||||
case CecDataPathType::MboxTitle:
|
case CecDataPathType::MboxTitle:
|
||||||
default: {}
|
default: {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@ public:
|
|||||||
return s_instance;
|
return s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartPlayback(const std::string& movie_file,
|
void StartPlayback(
|
||||||
std::function<void()> completion_callback = [] {});
|
const std::string& movie_file, std::function<void()> completion_callback = [] {});
|
||||||
void StartRecording(const std::string& movie_file);
|
void StartRecording(const std::string& movie_file);
|
||||||
|
|
||||||
/// Prepare to override the clock before playing back movies
|
/// Prepare to override the clock before playing back movies
|
||||||
|
@ -172,6 +172,7 @@ struct Values {
|
|||||||
|
|
||||||
bool dump_textures;
|
bool dump_textures;
|
||||||
bool custom_textures;
|
bool custom_textures;
|
||||||
|
bool preload_textures;
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
bool enable_dsp_lle;
|
bool enable_dsp_lle;
|
||||||
|
@ -217,8 +217,7 @@ void TestCommunication(const std::string& host, u16 port, u8 pad_index, u32 clie
|
|||||||
success_callback();
|
success_callback();
|
||||||
else
|
else
|
||||||
failure_callback();
|
failure_callback();
|
||||||
})
|
}).detach();
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CalibrationConfigurationJob::CalibrationConfigurationJob(
|
CalibrationConfigurationJob::CalibrationConfigurationJob(
|
||||||
@ -269,8 +268,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
|
|||||||
complete_event.Wait();
|
complete_event.Wait();
|
||||||
socket.Stop();
|
socket.Stop();
|
||||||
worker_thread.join();
|
worker_thread.join();
|
||||||
})
|
}).detach();
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CalibrationConfigurationJob::~CalibrationConfigurationJob() {
|
CalibrationConfigurationJob::~CalibrationConfigurationJob() {
|
||||||
|
@ -17,7 +17,8 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
|
|||||||
|
|
||||||
timing = std::make_unique<Core::Timing>();
|
timing = std::make_unique<Core::Timing>();
|
||||||
memory = std::make_unique<Memory::MemorySystem>();
|
memory = std::make_unique<Memory::MemorySystem>();
|
||||||
kernel = std::make_unique<Kernel::KernelSystem>(*memory, *timing, [] {}, 0);
|
kernel = std::make_unique<Kernel::KernelSystem>(
|
||||||
|
*memory, *timing, [] {}, 0);
|
||||||
|
|
||||||
kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0)));
|
kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0)));
|
||||||
page_table = &kernel->GetCurrentProcess()->vm_manager.page_table;
|
page_table = &kernel->GetCurrentProcess()->vm_manager.page_table;
|
||||||
|
@ -23,7 +23,8 @@ static std::shared_ptr<Object> MakeObject(Kernel::KernelSystem& kernel) {
|
|||||||
TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") {
|
TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel]") {
|
||||||
Core::Timing timing;
|
Core::Timing timing;
|
||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(
|
||||||
|
memory, timing, [] {}, 0);
|
||||||
auto [server, client] = kernel.CreateSessionPair();
|
auto [server, client] = kernel.CreateSessionPair();
|
||||||
HLERequestContext context(kernel, std::move(server), nullptr);
|
HLERequestContext context(kernel, std::move(server), nullptr);
|
||||||
|
|
||||||
@ -235,7 +236,8 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
|
|||||||
TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
|
||||||
Core::Timing timing;
|
Core::Timing timing;
|
||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(
|
||||||
|
memory, timing, [] {}, 0);
|
||||||
auto [server, client] = kernel.CreateSessionPair();
|
auto [server, client] = kernel.CreateSessionPair();
|
||||||
HLERequestContext context(kernel, std::move(server), nullptr);
|
HLERequestContext context(kernel, std::move(server), nullptr);
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@
|
|||||||
TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") {
|
TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory]") {
|
||||||
Core::Timing timing;
|
Core::Timing timing;
|
||||||
Memory::MemorySystem memory;
|
Memory::MemorySystem memory;
|
||||||
Kernel::KernelSystem kernel(memory, timing, [] {}, 0);
|
Kernel::KernelSystem kernel(
|
||||||
|
memory, timing, [] {}, 0);
|
||||||
SECTION("these regions should not be mapped on an empty process") {
|
SECTION("these regions should not be mapped on an empty process") {
|
||||||
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
|
||||||
CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false);
|
CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false);
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "common/math_util.h"
|
#include "common/math_util.h"
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
#include "common/texture.h"
|
||||||
#include "common/vector_math.h"
|
#include "common/vector_math.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/custom_tex_cache.h"
|
#include "core/custom_tex_cache.h"
|
||||||
@ -855,25 +856,6 @@ void CachedSurface::FlushGLBuffer(PAddr flush_start, PAddr flush_end) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this function to a better place
|
|
||||||
void FlipRGBA8Texture(std::vector<u8>& tex, u64 width, u64 height) {
|
|
||||||
ASSERT(tex.size() == width * height * 4);
|
|
||||||
const u64 line_size = width * 4;
|
|
||||||
// Thanks MSVC for not being able to make variable length arrays
|
|
||||||
u8* temp_row = new u8[line_size];
|
|
||||||
u32 offset_1;
|
|
||||||
u32 offset_2;
|
|
||||||
for (u64 line = 0; line < height / 2; line++) {
|
|
||||||
offset_1 = line * line_size;
|
|
||||||
offset_2 = (height - line - 1) * line_size;
|
|
||||||
// Swap lines
|
|
||||||
std::memcpy(temp_row, &tex[offset_1], line_size);
|
|
||||||
std::memcpy(&tex[offset_1], &tex[offset_2], line_size);
|
|
||||||
std::memcpy(&tex[offset_2], temp_row, line_size);
|
|
||||||
}
|
|
||||||
delete[] temp_row;
|
|
||||||
}
|
|
||||||
|
|
||||||
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
|
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
|
||||||
void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint read_fb_handle,
|
void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint read_fb_handle,
|
||||||
GLuint draw_fb_handle) {
|
GLuint draw_fb_handle) {
|
||||||
@ -893,7 +875,8 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r
|
|||||||
u32 png_width = 0;
|
u32 png_width = 0;
|
||||||
u32 png_height = 0;
|
u32 png_height = 0;
|
||||||
u64 tex_hash = 0;
|
u64 tex_hash = 0;
|
||||||
Common::Rectangle custom_rect = rect; // Required for rect to function properly with custom textures
|
Common::Rectangle custom_rect =
|
||||||
|
rect; // Required for rect to function properly with custom textures
|
||||||
|
|
||||||
if (Settings::values.dump_textures || Settings::values.custom_textures)
|
if (Settings::values.dump_textures || Settings::values.custom_textures)
|
||||||
tex_hash = Common::ComputeHash64(gl_buffer.get(), gl_buffer_size);
|
tex_hash = Common::ComputeHash64(gl_buffer.get(), gl_buffer_size);
|
||||||
@ -913,7 +896,7 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r
|
|||||||
lodepng_error_text(lodepng_ret));
|
lodepng_error_text(lodepng_ret));
|
||||||
else {
|
else {
|
||||||
LOG_INFO(Render_OpenGL, "Loaded custom texture from {}", load_path);
|
LOG_INFO(Render_OpenGL, "Loaded custom texture from {}", load_path);
|
||||||
FlipRGBA8Texture(decoded_png, png_width, png_height);
|
Common::FlipRGBA8Texture(decoded_png, png_width, png_height);
|
||||||
custom_tex_cache.CacheTexture(tex_hash, decoded_png, png_width, png_height);
|
custom_tex_cache.CacheTexture(tex_hash, decoded_png, png_width, png_height);
|
||||||
use_custom_tex = true;
|
use_custom_tex = true;
|
||||||
}
|
}
|
||||||
@ -1014,7 +997,7 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r
|
|||||||
glBindTexture(GL_TEXTURE_2D, target_tex);
|
glBindTexture(GL_TEXTURE_2D, target_tex);
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &decoded_texture[0]);
|
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &decoded_texture[0]);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
FlipRGBA8Texture(decoded_texture, width, height);
|
Common::FlipRGBA8Texture(decoded_texture, width, height);
|
||||||
u32 png_error = lodepng::encode(dump_path, decoded_texture, width, height);
|
u32 png_error = lodepng::encode(dump_path, decoded_texture, width, height);
|
||||||
if (png_error) {
|
if (png_error) {
|
||||||
LOG_CRITICAL(Render_OpenGL, "Failed to save decoded texture! {}",
|
LOG_CRITICAL(Render_OpenGL, "Failed to save decoded texture! {}",
|
||||||
@ -1034,8 +1017,7 @@ void CachedSurface::UploadGLTexture(const Common::Rectangle<u32>& rect, GLuint r
|
|||||||
scaled_rect.bottom *= res_scale;
|
scaled_rect.bottom *= res_scale;
|
||||||
|
|
||||||
BlitTextures(unscaled_tex.handle, {0, custom_rect.GetHeight(), custom_rect.GetWidth(), 0},
|
BlitTextures(unscaled_tex.handle, {0, custom_rect.GetHeight(), custom_rect.GetWidth(), 0},
|
||||||
texture.handle,
|
texture.handle, scaled_rect, type, read_fb_handle, draw_fb_handle);
|
||||||
scaled_rect, type, read_fb_handle, draw_fb_handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InvalidateAllWatcher();
|
InvalidateAllWatcher();
|
||||||
|
Loading…
Reference in New Issue
Block a user