mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	implement custom texture preload
This commit is contained in:
		
							parent
							
								
									657a129b60
								
							
						
					
					
						commit
						59b475a4b9
					
				
					 19 changed files with 139 additions and 126 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue