33#include " overlay_big_picture_game_details.h"
44#include " Emu/System.h"
55#include " Emu/system_config.h"
6- #include " Emu/system_utils.hpp"
7- #include " Loader/PSF.h"
6+ #include " Utilities/Thread.h"
87
98#include < algorithm>
109
@@ -51,12 +50,12 @@ namespace rsx
5150 : home_menu_page(x, y, width, height, false , parent, get_localized_string(localized_string_id::BIG_PICTURE_MENU_GAMES ))
5251 , m_on_game_selected(std::move(on_game_selected))
5352 {
54- m_no_games_text = std::make_unique<label>(get_localized_string (localized_string_id::BIG_PICTURE_NO_GAMES_FOUND ));
55- m_no_games_text ->set_font (" Arial" , 20 );
56- m_no_games_text ->set_pos (x, y + (height / 2 ) - 20 );
57- m_no_games_text ->set_size (width, 40 );
58- m_no_games_text ->align_text (text_align::center);
59- m_no_games_text ->back_color .a = 0 .f ;
53+ m_placeholder_text = std::make_unique<label>(get_localized_string (localized_string_id::BIG_PICTURE_LOADING ));
54+ m_placeholder_text ->set_font (" Arial" , 20 );
55+ m_placeholder_text ->set_pos (x, y + (height / 2 ) - 20 );
56+ m_placeholder_text ->set_size (width, 40 );
57+ m_placeholder_text ->align_text (text_align::center);
58+ m_placeholder_text ->back_color .a = 0 .f ;
6059
6160 // Bezel around game cover art.
6261 m_highlight = std::make_unique<rounded_rect>();
@@ -78,15 +77,24 @@ namespace rsx
7877
7978 m_details = std::make_unique<big_picture_game_details>(x, y, width, height);
8079
81- reload ();
80+ start_reload ();
8281 }
8382
84- big_picture_game_grid::~big_picture_game_grid () = default ;
83+ big_picture_game_grid::~big_picture_game_grid ()
84+ {
85+ if (m_game_enumeration_thread)
86+ {
87+ *m_game_enumeration_thread = thread_state::aborting; // abort
88+ (*m_game_enumeration_thread)(); // wait
89+ m_game_enumeration_thread.reset (); // join
90+ }
91+ }
8592
86- void big_picture_game_grid::reload ()
93+ void big_picture_game_grid::start_reload ()
8794 {
8895 rsx_log.notice (" Big Picture Mode: reload() start" );
8996
97+ m_loading = true ;
9098 m_games.clear ();
9199 m_tiles.clear ();
92100
@@ -97,43 +105,100 @@ namespace rsx
97105 m_game_enumeration.set_prefer_game_data_icons (true );
98106 m_game_enumeration.set_play_hover_movies (true );
99107 m_game_enumeration.set_play_hover_music (true );
100- m_game_enumeration.set_canceled_callback ([](){ return Emu.IsStopped (); });
101-
102- // Parse directories
103- m_game_enumeration.parse_directories ();
108+ m_game_enumeration.set_canceled_callback ([](){ return thread_ctrl::state () == thread_state::aborting; });
104109
105- // Add VFS entry
106- m_game_enumeration.add_vfs_entry ();
110+ m_game_enumeration_thread = std::make_unique<named_thread<std::function<void ()>>>(" BPM Reload" , [this ]()
111+ {
112+ // Parse directories
113+ m_game_enumeration.parse_directories ();
107114
108- // Remove duplicate entries
109- m_game_enumeration.remove_duplicates ();
115+ // Add VFS entry
116+ m_game_enumeration.add_vfs_entry ();
110117
111- // Parse entries
112- for (const game_enumeration<big_picture_game_entry>::path_entry& entry : m_game_enumeration.path_entries ())
113- {
114- m_game_enumeration.parse_entry (entry);
115- }
118+ // Remove duplicate entries
119+ m_game_enumeration.remove_duplicates ();
116120
117- // Try to update the app version for disc games if there is a patch
118- // Also try to find updated game icons and movies
119- m_game_enumeration.apply_patches ();
121+ // Parse entries (multithreaded)
122+ const std::vector<game_enumeration<big_picture_game_entry>::path_entry>& entries = m_game_enumeration.path_entries ();
123+ const usz thread_count = std::min<usz>(utils::get_thread_count (), entries.size ());
124+ if (thread_count > 1 )
125+ {
126+ atomic_t <usz> entry_indexer = 0 ;
127+ const auto parse_entries = [this , &entry_indexer, &entries]()
128+ {
129+ while (thread_ctrl::state () != thread_state::aborting)
130+ {
131+ // Make sure entry_indexer does not exceed m_install_entries
132+ const usz index = entry_indexer.fetch_op ([&entries](usz& v)
133+ {
134+ if (v < entries.size ())
135+ {
136+ v++;
137+ return true ;
138+ }
139+
140+ return false ;
141+ }).first ;
142+
143+ if (index >= entries.size ())
144+ {
145+ break ;
146+ }
147+
148+ m_game_enumeration.parse_entry (entries[index]);
149+ }
150+ };
151+ named_thread_group workers (" BPM Parser " sv, ::narrow<u32 >(thread_count) - 1 , [&parse_entries]()
152+ {
153+ parse_entries ();
154+ });
120155
121- // Get final enumerated games
122- for (big_picture_game_entry& game : m_game_enumeration.take_games ())
123- {
124- if (!game.bootable ) continue ; // Let's restrict this to bootable entries
156+ parse_entries ();
125157
126- m_games.push_back (std::move (game));
127- }
158+ workers.join ();
159+ }
160+ else
161+ {
162+ for (const game_enumeration<big_picture_game_entry>::path_entry& entry : entries)
163+ {
164+ m_game_enumeration.parse_entry (entry);
165+ }
166+ }
128167
129- // Reset enumeration
130- m_game_enumeration.clear (true );
168+ // Try to update the app version for disc games if there is a patch
169+ // Also try to find updated game icons and movies
170+ m_game_enumeration.apply_patches ();
131171
132- // Sort by name
133- std::sort (m_games.begin (), m_games.end (), [](const big_picture_game_entry& a, const big_picture_game_entry& b)
134- {
135- return a.name < b.name ;
172+ // Get final enumerated games
173+ for (big_picture_game_entry& game : m_game_enumeration.take_games ())
174+ {
175+ if (!game.bootable ) continue ; // Let's restrict this to bootable entries
176+
177+ m_games.push_back (std::move (game));
178+ }
179+
180+ // Reset enumeration
181+ m_game_enumeration.clear (true );
182+
183+ // Sort by name
184+ std::sort (m_games.begin (), m_games.end (), [](const big_picture_game_entry& a, const big_picture_game_entry& b)
185+ {
186+ return a.name < b.name ;
187+ });
188+
189+ finish_reload ();
136190 });
191+ }
192+
193+ void big_picture_game_grid::finish_reload ()
194+ {
195+ std::lock_guard lock (m_reload_mutex);
196+
197+ if (thread_ctrl::state () == thread_state::aborting)
198+ {
199+ m_loading = false ;
200+ return ;
201+ }
137202
138203 m_grid = std::make_unique<vertical_layout>();
139204 m_grid->set_pos (x, y);
@@ -173,12 +238,19 @@ namespace rsx
173238
174239 m_selected_index = m_tiles.empty () ? 0 : std::clamp (m_selected_index, 0 , static_cast <s32>(m_tiles.size ()) - 1 );
175240
176- if (!m_tiles.empty ())
241+ if (m_tiles.empty ())
242+ {
243+ m_placeholder_text->set_text (get_localized_string (localized_string_id::BIG_PICTURE_NO_GAMES_FOUND ));
244+ }
245+ else
177246 {
178247 select_tile (m_selected_index);
179248 }
180249
181250 rsx_log.notice (" Big Picture Mode: reload() finished, games=%u, tiles=%u" , m_games.size (), m_tiles.size ());
251+
252+ m_loading = false ;
253+ refresh ();
182254 }
183255
184256 void big_picture_game_grid::select_tile (s32 index)
@@ -212,7 +284,7 @@ namespace rsx
212284 }
213285
214286 m_grid->scroll_offset_value = static_cast <u16 >(std::clamp (offset, 0 , max_offset));
215- m_grid->refresh ();
287+ m_grid->refresh ();
216288 }
217289
218290 const big_picture_game_tile* tile = m_tiles[m_selected_index];
@@ -224,10 +296,14 @@ namespace rsx
224296 m_highlight->set_size (icon->w + bezel_margin * 2 , icon->h + bezel_margin * 2 );
225297 m_highlight->set_sinus_offset (1 .6f );
226298 m_highlight->refresh ();
299+
300+ refresh ();
227301 }
228302
229303 page_navigation big_picture_game_grid::handle_button_press (pad_button button_press, bool is_auto_repeat, u64 auto_repeat_interval_ms)
230304 {
305+ if (m_loading) return page_navigation::stay;
306+
231307 const bool do_play_sound = !is_auto_repeat || auto_repeat_interval_ms >= user_interface::m_auto_repeat_ms_interval_default;
232308
233309 if (m_details && m_details->is_visible ())
@@ -239,6 +315,7 @@ namespace rsx
239315 {
240316 case big_picture_game_details::result::back:
241317 m_details->hide ();
318+ refresh ();
242319 break ;
243320 case big_picture_game_details::result::start:
244321 {
@@ -252,6 +329,7 @@ namespace rsx
252329 m_on_game_selected (info.path , info.serial );
253330 rsx_log.notice (" Big Picture Mode: on_game_selected callback returned" );
254331 }
332+ refresh ();
255333 break ;
256334 }
257335 default :
@@ -312,6 +390,7 @@ namespace rsx
312390 rsx_log.notice (" Big Picture Mode: opening details for index=%d" , m_selected_index);
313391 m_details->show (m_games[m_selected_index], m_tiles[m_selected_index]->get_icon_data ());
314392 rsx_log.notice (" Big Picture Mode: details shown" );
393+ refresh ();
315394 return page_navigation::stay;
316395 case pad_button::circle:
317396 play_sound (sound_effect::cancel);
@@ -335,36 +414,46 @@ namespace rsx
335414
336415 compiled_resource& big_picture_game_grid::get_compiled ()
337416 {
338- m_compiled_grid.clear ();
417+ if (is_compiled ())
418+ {
419+ return compiled_resources;
420+ }
421+
422+ m_is_compiled = true ;
423+ compiled_resources.clear ();
424+
425+ if (!visible)
426+ {
427+ return compiled_resources;
428+ }
429+
430+ std::lock_guard lock (m_reload_mutex);
339431
340432 if (m_tiles.empty ())
341433 {
342- m_compiled_grid .add (m_no_games_text ->get_compiled ());
434+ compiled_resources .add (m_placeholder_text ->get_compiled ());
343435 }
344436 else if (m_grid)
345437 {
346- m_compiled_grid .add (m_grid->get_compiled ());
347- m_compiled_grid .add (m_highlight->get_compiled ());
438+ compiled_resources .add (m_grid->get_compiled ());
439+ compiled_resources .add (m_highlight->get_compiled ());
348440 }
349441
350- const bool details_visible = m_details && m_details->is_visible ();
351-
352- if (!details_visible)
442+ if (m_details && m_details->is_visible ())
353443 {
354- m_compiled_grid.add (m_back_hint.get_compiled ());
444+ compiled_resources.add (m_details->get_compiled ());
445+ }
446+ else
447+ {
448+ compiled_resources.add (m_back_hint.get_compiled ());
355449
356450 if (!m_tiles.empty ())
357451 {
358- m_compiled_grid .add (m_select_hint.get_compiled ());
452+ compiled_resources .add (m_select_hint.get_compiled ());
359453 }
360454 }
361455
362- if (m_details)
363- {
364- m_compiled_grid.add (m_details->get_compiled ());
365- }
366-
367- return m_compiled_grid;
456+ return compiled_resources;
368457 }
369458 }
370459}
0 commit comments