diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt | 52 | ||||
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt | 7 | ||||
| -rw-r--r-- | src/audio_core/sink/cubeb_sink.cpp | 2 | ||||
| -rw-r--r-- | src/audio_core/sink/sdl2_sink.cpp | 2 | ||||
| -rw-r--r-- | src/audio_core/sink/sink_stream.cpp | 12 | ||||
| -rw-r--r-- | src/audio_core/sink/sink_stream.h | 6 | ||||
| -rw-r--r-- | src/core/arm/arm_interface.cpp | 16 | ||||
| -rw-r--r-- | src/core/core_timing.cpp | 2 | ||||
| -rw-r--r-- | src/core/core_timing.h | 2 |
9 files changed, 64 insertions, 37 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt index 0c82cdba8..2ef638559 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/GameAdapter.kt | |||
| @@ -22,12 +22,16 @@ import androidx.core.graphics.drawable.toBitmap | |||
| 22 | import androidx.core.graphics.drawable.toDrawable | 22 | import androidx.core.graphics.drawable.toDrawable |
| 23 | import androidx.documentfile.provider.DocumentFile | 23 | import androidx.documentfile.provider.DocumentFile |
| 24 | import androidx.lifecycle.ViewModelProvider | 24 | import androidx.lifecycle.ViewModelProvider |
| 25 | import androidx.lifecycle.lifecycleScope | ||
| 25 | import androidx.navigation.findNavController | 26 | import androidx.navigation.findNavController |
| 26 | import androidx.preference.PreferenceManager | 27 | import androidx.preference.PreferenceManager |
| 27 | import androidx.recyclerview.widget.AsyncDifferConfig | 28 | import androidx.recyclerview.widget.AsyncDifferConfig |
| 28 | import androidx.recyclerview.widget.DiffUtil | 29 | import androidx.recyclerview.widget.DiffUtil |
| 29 | import androidx.recyclerview.widget.ListAdapter | 30 | import androidx.recyclerview.widget.ListAdapter |
| 30 | import androidx.recyclerview.widget.RecyclerView | 31 | import androidx.recyclerview.widget.RecyclerView |
| 32 | import kotlinx.coroutines.Dispatchers | ||
| 33 | import kotlinx.coroutines.launch | ||
| 34 | import kotlinx.coroutines.withContext | ||
| 31 | import org.yuzu.yuzu_emu.HomeNavigationDirections | 35 | import org.yuzu.yuzu_emu.HomeNavigationDirections |
| 32 | import org.yuzu.yuzu_emu.R | 36 | import org.yuzu.yuzu_emu.R |
| 33 | import org.yuzu.yuzu_emu.YuzuApplication | 37 | import org.yuzu.yuzu_emu.YuzuApplication |
| @@ -92,28 +96,34 @@ class GameAdapter(private val activity: AppCompatActivity) : | |||
| 92 | data = Uri.parse(holder.game.path) | 96 | data = Uri.parse(holder.game.path) |
| 93 | } | 97 | } |
| 94 | 98 | ||
| 95 | val layerDrawable = ResourcesCompat.getDrawable( | 99 | activity.lifecycleScope.launch { |
| 96 | YuzuApplication.appContext.resources, | 100 | withContext(Dispatchers.IO) { |
| 97 | R.drawable.shortcut, | 101 | val layerDrawable = ResourcesCompat.getDrawable( |
| 98 | null | 102 | YuzuApplication.appContext.resources, |
| 99 | ) as LayerDrawable | 103 | R.drawable.shortcut, |
| 100 | layerDrawable.setDrawableByLayerId( | 104 | null |
| 101 | R.id.shortcut_foreground, | 105 | ) as LayerDrawable |
| 102 | GameIconUtils.getGameIcon(holder.game).toDrawable(YuzuApplication.appContext.resources) | 106 | layerDrawable.setDrawableByLayerId( |
| 103 | ) | 107 | R.id.shortcut_foreground, |
| 104 | val inset = YuzuApplication.appContext.resources | 108 | GameIconUtils.getGameIcon(activity, holder.game) |
| 105 | .getDimensionPixelSize(R.dimen.icon_inset) | 109 | .toDrawable(YuzuApplication.appContext.resources) |
| 106 | layerDrawable.setLayerInset(1, inset, inset, inset, inset) | ||
| 107 | val shortcut = ShortcutInfoCompat.Builder(YuzuApplication.appContext, holder.game.path) | ||
| 108 | .setShortLabel(holder.game.title) | ||
| 109 | .setIcon( | ||
| 110 | IconCompat.createWithAdaptiveBitmap( | ||
| 111 | layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888) | ||
| 112 | ) | 110 | ) |
| 113 | ) | 111 | val inset = YuzuApplication.appContext.resources |
| 114 | .setIntent(openIntent) | 112 | .getDimensionPixelSize(R.dimen.icon_inset) |
| 115 | .build() | 113 | layerDrawable.setLayerInset(1, inset, inset, inset, inset) |
| 116 | ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) | 114 | val shortcut = |
| 115 | ShortcutInfoCompat.Builder(YuzuApplication.appContext, holder.game.path) | ||
| 116 | .setShortLabel(holder.game.title) | ||
| 117 | .setIcon( | ||
| 118 | IconCompat.createWithAdaptiveBitmap( | ||
| 119 | layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888) | ||
| 120 | ) | ||
| 121 | ) | ||
| 122 | .setIntent(openIntent) | ||
| 123 | .build() | ||
| 124 | ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) | ||
| 125 | } | ||
| 126 | } | ||
| 117 | 127 | ||
| 118 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game) | 128 | val action = HomeNavigationDirections.actionGlobalEmulationActivity(holder.game) |
| 119 | view.findNavController().navigate(action) | 129 | view.findNavController().navigate(action) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt index 654d62f52..2e9b0beb8 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameIconUtils.kt | |||
| @@ -8,9 +8,9 @@ import android.graphics.BitmapFactory | |||
| 8 | import android.widget.ImageView | 8 | import android.widget.ImageView |
| 9 | import androidx.core.graphics.drawable.toBitmap | 9 | import androidx.core.graphics.drawable.toBitmap |
| 10 | import androidx.core.graphics.drawable.toDrawable | 10 | import androidx.core.graphics.drawable.toDrawable |
| 11 | import androidx.lifecycle.LifecycleOwner | ||
| 11 | import coil.ImageLoader | 12 | import coil.ImageLoader |
| 12 | import coil.decode.DataSource | 13 | import coil.decode.DataSource |
| 13 | import coil.executeBlocking | ||
| 14 | import coil.fetch.DrawableResult | 14 | import coil.fetch.DrawableResult |
| 15 | import coil.fetch.FetchResult | 15 | import coil.fetch.FetchResult |
| 16 | import coil.fetch.Fetcher | 16 | import coil.fetch.Fetcher |
| @@ -76,12 +76,13 @@ object GameIconUtils { | |||
| 76 | imageLoader.enqueue(request) | 76 | imageLoader.enqueue(request) |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | fun getGameIcon(game: Game): Bitmap { | 79 | suspend fun getGameIcon(lifecycleOwner: LifecycleOwner, game: Game): Bitmap { |
| 80 | val request = ImageRequest.Builder(YuzuApplication.appContext) | 80 | val request = ImageRequest.Builder(YuzuApplication.appContext) |
| 81 | .data(game) | 81 | .data(game) |
| 82 | .lifecycle(lifecycleOwner) | ||
| 82 | .error(R.drawable.default_icon) | 83 | .error(R.drawable.default_icon) |
| 83 | .build() | 84 | .build() |
| 84 | return imageLoader.executeBlocking(request) | 85 | return imageLoader.execute(request) |
| 85 | .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888) | 86 | .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888) |
| 86 | } | 87 | } |
| 87 | } | 88 | } |
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp index bbb598bc5..51a23fe15 100644 --- a/src/audio_core/sink/cubeb_sink.cpp +++ b/src/audio_core/sink/cubeb_sink.cpp | |||
| @@ -146,7 +146,7 @@ public: | |||
| 146 | return; | 146 | return; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | paused = true; | 149 | SignalPause(); |
| 150 | if (cubeb_stream_stop(stream_backend) != CUBEB_OK) { | 150 | if (cubeb_stream_stop(stream_backend) != CUBEB_OK) { |
| 151 | LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream"); | 151 | LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream"); |
| 152 | } | 152 | } |
diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp index 7b89151de..96e0efce2 100644 --- a/src/audio_core/sink/sdl2_sink.cpp +++ b/src/audio_core/sink/sdl2_sink.cpp | |||
| @@ -111,7 +111,7 @@ public: | |||
| 111 | if (device == 0 || paused) { | 111 | if (device == 0 || paused) { |
| 112 | return; | 112 | return; |
| 113 | } | 113 | } |
| 114 | paused = true; | 114 | SignalPause(); |
| 115 | SDL_PauseAudioDevice(device, 1); | 115 | SDL_PauseAudioDevice(device, 1); |
| 116 | } | 116 | } |
| 117 | 117 | ||
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index d66d04fae..2a09db599 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp | |||
| @@ -282,11 +282,19 @@ u64 SinkStream::GetExpectedPlayedSampleCount() { | |||
| 282 | void SinkStream::WaitFreeSpace(std::stop_token stop_token) { | 282 | void SinkStream::WaitFreeSpace(std::stop_token stop_token) { |
| 283 | std::unique_lock lk{release_mutex}; | 283 | std::unique_lock lk{release_mutex}; |
| 284 | release_cv.wait_for(lk, std::chrono::milliseconds(5), | 284 | release_cv.wait_for(lk, std::chrono::milliseconds(5), |
| 285 | [this]() { return queued_buffers < max_queue_size; }); | 285 | [this]() { return paused || queued_buffers < max_queue_size; }); |
| 286 | if (queued_buffers > max_queue_size + 3) { | 286 | if (queued_buffers > max_queue_size + 3) { |
| 287 | Common::CondvarWait(release_cv, lk, stop_token, | 287 | Common::CondvarWait(release_cv, lk, stop_token, |
| 288 | [this] { return queued_buffers < max_queue_size; }); | 288 | [this] { return paused || queued_buffers < max_queue_size; }); |
| 289 | } | 289 | } |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | void SinkStream::SignalPause() { | ||
| 293 | { | ||
| 294 | std::scoped_lock lk{release_mutex}; | ||
| 295 | paused = true; | ||
| 296 | } | ||
| 297 | release_cv.notify_one(); | ||
| 298 | } | ||
| 299 | |||
| 292 | } // namespace AudioCore::Sink | 300 | } // namespace AudioCore::Sink |
diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h index 6a4996ca3..f2ccd19b8 100644 --- a/src/audio_core/sink/sink_stream.h +++ b/src/audio_core/sink/sink_stream.h | |||
| @@ -214,6 +214,12 @@ public: | |||
| 214 | void WaitFreeSpace(std::stop_token stop_token); | 214 | void WaitFreeSpace(std::stop_token stop_token); |
| 215 | 215 | ||
| 216 | protected: | 216 | protected: |
| 217 | /** | ||
| 218 | * Unblocks the ADSP if the stream is paused. | ||
| 219 | */ | ||
| 220 | void SignalPause(); | ||
| 221 | |||
| 222 | protected: | ||
| 217 | /// Core system | 223 | /// Core system |
| 218 | Core::System& system; | 224 | Core::System& system; |
| 219 | /// Type of this stream | 225 | /// Type of this stream |
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 5e27dde58..558fba5bd 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp | |||
| @@ -153,6 +153,14 @@ void ARM_Interface::Run() { | |||
| 153 | Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())}; | 153 | Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())}; |
| 154 | HaltReason hr{}; | 154 | HaltReason hr{}; |
| 155 | 155 | ||
| 156 | // If the thread is scheduled for termination, exit the thread. | ||
| 157 | if (current_thread->HasDpc()) { | ||
| 158 | if (current_thread->IsTerminationRequested()) { | ||
| 159 | current_thread->Exit(); | ||
| 160 | UNREACHABLE(); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 156 | // Notify the debugger and go to sleep if a step was performed | 164 | // Notify the debugger and go to sleep if a step was performed |
| 157 | // and this thread has been scheduled again. | 165 | // and this thread has been scheduled again. |
| 158 | if (current_thread->GetStepState() == StepState::StepPerformed) { | 166 | if (current_thread->GetStepState() == StepState::StepPerformed) { |
| @@ -174,14 +182,6 @@ void ARM_Interface::Run() { | |||
| 174 | } | 182 | } |
| 175 | system.ExitCPUProfile(); | 183 | system.ExitCPUProfile(); |
| 176 | 184 | ||
| 177 | // If the thread is scheduled for termination, exit the thread. | ||
| 178 | if (current_thread->HasDpc()) { | ||
| 179 | if (current_thread->IsTerminationRequested()) { | ||
| 180 | current_thread->Exit(); | ||
| 181 | UNREACHABLE(); | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | // Notify the debugger and go to sleep if a breakpoint was hit, | 185 | // Notify the debugger and go to sleep if a breakpoint was hit, |
| 186 | // or if the thread is unable to continue for any reason. | 186 | // or if the thread is unable to continue for any reason. |
| 187 | if (True(hr & HaltReason::InstructionBreakpoint) || True(hr & HaltReason::PrefetchAbort)) { | 187 | if (True(hr & HaltReason::InstructionBreakpoint) || True(hr & HaltReason::PrefetchAbort)) { |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index e671b270f..d6b5abc68 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -76,6 +76,7 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { | |||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | void CoreTiming::ClearPendingEvents() { | 78 | void CoreTiming::ClearPendingEvents() { |
| 79 | std::scoped_lock lock{basic_lock}; | ||
| 79 | event_queue.clear(); | 80 | event_queue.clear(); |
| 80 | } | 81 | } |
| 81 | 82 | ||
| @@ -113,6 +114,7 @@ bool CoreTiming::IsRunning() const { | |||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | bool CoreTiming::HasPendingEvents() const { | 116 | bool CoreTiming::HasPendingEvents() const { |
| 117 | std::scoped_lock lock{basic_lock}; | ||
| 116 | return !(wait_set && event_queue.empty()); | 118 | return !(wait_set && event_queue.empty()); |
| 117 | } | 119 | } |
| 118 | 120 | ||
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 26a8b93a7..21548f0a9 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -161,7 +161,7 @@ private: | |||
| 161 | std::shared_ptr<EventType> ev_lost; | 161 | std::shared_ptr<EventType> ev_lost; |
| 162 | Common::Event event{}; | 162 | Common::Event event{}; |
| 163 | Common::Event pause_event{}; | 163 | Common::Event pause_event{}; |
| 164 | std::mutex basic_lock; | 164 | mutable std::mutex basic_lock; |
| 165 | std::mutex advance_lock; | 165 | std::mutex advance_lock; |
| 166 | std::unique_ptr<std::jthread> timer_thread; | 166 | std::unique_ptr<std::jthread> timer_thread; |
| 167 | std::atomic<bool> paused{}; | 167 | std::atomic<bool> paused{}; |