summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/AndroidManifest.xml1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt13
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt17
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt48
-rw-r--r--src/audio_core/sink/cubeb_sink.cpp7
-rw-r--r--src/audio_core/sink/sink_details.cpp4
-rw-r--r--src/core/hle/service/audio/hwopus.cpp49
-rw-r--r--src/core/hle/service/audio/hwopus.h5
-rw-r--r--src/video_core/host1x/codecs/codec.cpp3
9 files changed, 89 insertions, 58 deletions
diff --git a/src/android/app/src/main/AndroidManifest.xml b/src/android/app/src/main/AndroidManifest.xml
index 36e2dac98..933244140 100644
--- a/src/android/app/src/main/AndroidManifest.xml
+++ b/src/android/app/src/main/AndroidManifest.xml
@@ -56,7 +56,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
56 android:name="org.yuzu.yuzu_emu.activities.EmulationActivity" 56 android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
57 android:theme="@style/Theme.Yuzu.Main" 57 android:theme="@style/Theme.Yuzu.Main"
58 android:launchMode="singleTop" 58 android:launchMode="singleTop"
59 android:screenOrientation="userLandscape"
60 android:supportsPictureInPicture="true" 59 android:supportsPictureInPicture="true"
61 android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode" 60 android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
62 android:exported="true"> 61 android:exported="true">
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
index a5af5a7ae..e6fffc832 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
@@ -11,7 +11,6 @@ import android.view.View
11import android.view.ViewGroup.MarginLayoutParams 11import android.view.ViewGroup.MarginLayoutParams
12import android.widget.Toast 12import android.widget.Toast
13import androidx.activity.OnBackPressedCallback 13import androidx.activity.OnBackPressedCallback
14import androidx.activity.result.ActivityResultLauncher
15import androidx.activity.viewModels 14import androidx.activity.viewModels
16import androidx.appcompat.app.AppCompatActivity 15import androidx.appcompat.app.AppCompatActivity
17import androidx.core.view.ViewCompat 16import androidx.core.view.ViewCompat
@@ -246,17 +245,5 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
246 settings.putExtra(ARG_GAME_ID, gameId) 245 settings.putExtra(ARG_GAME_ID, gameId)
247 context.startActivity(settings) 246 context.startActivity(settings)
248 } 247 }
249
250 fun launch(
251 context: Context,
252 launcher: ActivityResultLauncher<Intent>,
253 menuTag: String?,
254 gameId: String?
255 ) {
256 val settings = Intent(context, SettingsActivity::class.java)
257 settings.putExtra(ARG_MENU_TAG, menuTag)
258 settings.putExtra(ARG_GAME_ID, gameId)
259 launcher.launch(settings)
260 }
261 } 248 }
262} 249}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 25b9d4018..09e93a017 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -7,7 +7,6 @@ import android.annotation.SuppressLint
7import android.app.AlertDialog 7import android.app.AlertDialog
8import android.content.Context 8import android.content.Context
9import android.content.DialogInterface 9import android.content.DialogInterface
10import android.content.Intent
11import android.content.SharedPreferences 10import android.content.SharedPreferences
12import android.content.pm.ActivityInfo 11import android.content.pm.ActivityInfo
13import android.content.res.Configuration 12import android.content.res.Configuration
@@ -19,8 +18,6 @@ import android.util.Rational
19import android.view.* 18import android.view.*
20import android.widget.TextView 19import android.widget.TextView
21import androidx.activity.OnBackPressedCallback 20import androidx.activity.OnBackPressedCallback
22import androidx.activity.result.ActivityResultLauncher
23import androidx.activity.result.contract.ActivityResultContracts
24import androidx.appcompat.widget.PopupMenu 21import androidx.appcompat.widget.PopupMenu
25import androidx.core.content.res.ResourcesCompat 22import androidx.core.content.res.ResourcesCompat
26import androidx.core.graphics.Insets 23import androidx.core.graphics.Insets
@@ -66,8 +63,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
66 63
67 private var isInFoldableLayout = false 64 private var isInFoldableLayout = false
68 65
69 private lateinit var onReturnFromSettings: ActivityResultLauncher<Intent>
70
71 override fun onAttach(context: Context) { 66 override fun onAttach(context: Context) {
72 super.onAttach(context) 67 super.onAttach(context)
73 if (context is EmulationActivity) { 68 if (context is EmulationActivity) {
@@ -81,11 +76,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
81 .collect { updateFoldableLayout(context, it) } 76 .collect { updateFoldableLayout(context, it) }
82 } 77 }
83 } 78 }
84
85 onReturnFromSettings = context.activityResultRegistry.register(
86 "SettingsResult",
87 ActivityResultContracts.StartActivityForResult()
88 ) { updateScreenLayout() }
89 } else { 79 } else {
90 throw IllegalStateException("EmulationFragment must have EmulationActivity parent") 80 throw IllegalStateException("EmulationFragment must have EmulationActivity parent")
91 } 81 }
@@ -149,12 +139,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
149 } 139 }
150 140
151 R.id.menu_settings -> { 141 R.id.menu_settings -> {
152 SettingsActivity.launch( 142 SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "")
153 requireContext(),
154 onReturnFromSettings,
155 SettingsFile.FILE_NAME_CONFIG,
156 ""
157 )
158 true 143 true
159 } 144 }
160 145
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt
index 685ccaa76..2f0868c63 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt
@@ -7,7 +7,6 @@ import android.content.Context
7import android.util.AttributeSet 7import android.util.AttributeSet
8import android.util.Rational 8import android.util.Rational
9import android.view.SurfaceView 9import android.view.SurfaceView
10import kotlin.math.roundToInt
11 10
12class FixedRatioSurfaceView @JvmOverloads constructor( 11class FixedRatioSurfaceView @JvmOverloads constructor(
13 context: Context, 12 context: Context,
@@ -22,27 +21,44 @@ class FixedRatioSurfaceView @JvmOverloads constructor(
22 */ 21 */
23 fun setAspectRatio(ratio: Rational?) { 22 fun setAspectRatio(ratio: Rational?) {
24 aspectRatio = ratio?.toFloat() ?: 0f 23 aspectRatio = ratio?.toFloat() ?: 0f
24 requestLayout()
25 } 25 }
26 26
27 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { 27 override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
28 super.onMeasure(widthMeasureSpec, heightMeasureSpec) 28 val displayWidth: Float = MeasureSpec.getSize(widthMeasureSpec).toFloat()
29 val width = MeasureSpec.getSize(widthMeasureSpec) 29 val displayHeight: Float = MeasureSpec.getSize(heightMeasureSpec).toFloat()
30 val height = MeasureSpec.getSize(heightMeasureSpec)
31 if (aspectRatio != 0f) { 30 if (aspectRatio != 0f) {
32 val newWidth: Int 31 val displayAspect = displayWidth / displayHeight
33 val newHeight: Int 32 if (displayAspect < aspectRatio) {
34 if (height * aspectRatio < width) { 33 // Max out width
35 newWidth = (height * aspectRatio).roundToInt() 34 val halfHeight = displayHeight / 2
36 newHeight = height 35 val surfaceHeight = displayWidth / aspectRatio
36 val newTop: Float = halfHeight - (surfaceHeight / 2)
37 val newBottom: Float = halfHeight + (surfaceHeight / 2)
38 super.onMeasure(
39 widthMeasureSpec,
40 MeasureSpec.makeMeasureSpec(
41 newBottom.toInt() - newTop.toInt(),
42 MeasureSpec.EXACTLY
43 )
44 )
45 return
37 } else { 46 } else {
38 newWidth = width 47 // Max out height
39 newHeight = (width / aspectRatio).roundToInt() 48 val halfWidth = displayWidth / 2
49 val surfaceWidth = displayHeight * aspectRatio
50 val newLeft: Float = halfWidth - (surfaceWidth / 2)
51 val newRight: Float = halfWidth + (surfaceWidth / 2)
52 super.onMeasure(
53 MeasureSpec.makeMeasureSpec(
54 newRight.toInt() - newLeft.toInt(),
55 MeasureSpec.EXACTLY
56 ),
57 heightMeasureSpec
58 )
59 return
40 } 60 }
41 val left = (width - newWidth) / 2
42 val top = (height - newHeight) / 2
43 setLeftTopRightBottom(left, top, left + newWidth, top + newHeight)
44 } else {
45 setLeftTopRightBottom(0, 0, width, height)
46 } 61 }
62 super.onMeasure(widthMeasureSpec, heightMeasureSpec)
47 } 63 }
48} 64}
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp
index 04d98a865..bbb598bc5 100644
--- a/src/audio_core/sink/cubeb_sink.cpp
+++ b/src/audio_core/sink/cubeb_sink.cpp
@@ -364,7 +364,7 @@ bool IsCubebSuitable() {
364 } 364 }
365#endif 365#endif
366 366
367 // Test min latency 367 // Get min latency
368 cubeb_stream_params params{}; 368 cubeb_stream_params params{};
369 params.rate = TargetSampleRate; 369 params.rate = TargetSampleRate;
370 params.channels = 2; 370 params.channels = 2;
@@ -380,11 +380,6 @@ bool IsCubebSuitable() {
380 } 380 }
381 latency = std::max(latency, TargetSampleCount * 2); 381 latency = std::max(latency, TargetSampleCount * 2);
382 382
383 if (latency > TargetSampleCount * 3) {
384 LOG_ERROR(Audio_Sink, "Cubeb latency is too high, it is not suitable.");
385 return false;
386 }
387
388 // Test opening a device with standard parameters 383 // Test opening a device with standard parameters
389 cubeb_devid output_device{0}; 384 cubeb_devid output_device{0};
390 cubeb_devid input_device{0}; 385 cubeb_devid input_device{0};
diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp
index 6bec8ee7c..7c9a4e3ac 100644
--- a/src/audio_core/sink/sink_details.cpp
+++ b/src/audio_core/sink/sink_details.cpp
@@ -83,8 +83,8 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
83 break; 83 break;
84 } 84 }
85 } 85 }
86 LOG_ERROR(Service_Audio, "Auto-selecting the {} backend", 86 LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
87 Settings::CanonicalizeEnum(iter->id)); 87 Settings::CanonicalizeEnum(iter->id));
88 } else { 88 } else {
89 if (iter != std::end(sink_details) && !iter->is_suitable()) { 89 if (iter != std::end(sink_details) && !iter->is_suitable()) {
90 LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null", 90 LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null",
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index fa77007f3..4a8276ed1 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -174,7 +174,7 @@ public:
174 {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"}, 174 {6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"},
175 {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"}, 175 {7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
176 {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"}, 176 {8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
177 {9, nullptr, "DecodeInterleavedForMultiStream"}, 177 {9, &IHardwareOpusDecoderManager::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"},
178 }; 178 };
179 // clang-format on 179 // clang-format on
180 180
@@ -206,6 +206,16 @@ private:
206 decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior); 206 decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
207 } 207 }
208 208
209 void DecodeInterleavedForMultiStream(HLERequestContext& ctx) {
210 LOG_DEBUG(Audio, "called");
211
212 IPC::RequestParser rp{ctx};
213 const auto extra_behavior = rp.Pop<bool>() ? OpusDecoderState::ExtraBehavior::ResetContext
214 : OpusDecoderState::ExtraBehavior::None;
215
216 decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
217 }
218
209 OpusDecoderState decoder_state; 219 OpusDecoderState decoder_state;
210}; 220};
211 221
@@ -354,6 +364,40 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
354 system, OpusDecoderState{std::move(decoder), sample_rate, channel_count}); 364 system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
355} 365}
356 366
367void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
368 OpusMultiStreamParametersEx params;
369 std::memcpy(&params, ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
370
371 const auto& sample_rate = params.sample_rate;
372 const auto& channel_count = params.channel_count;
373
374 LOG_INFO(
375 Audio,
376 "called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}",
377 sample_rate, channel_count, params.number_streams, params.number_stereo_streams);
378
379 ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
380 sample_rate == 12000 || sample_rate == 8000,
381 "Invalid sample rate");
382
383 int error = 0;
384 OpusDecoderPtr decoder{opus_multistream_decoder_create(
385 sample_rate, static_cast<int>(channel_count), params.number_streams,
386 params.number_stereo_streams, params.channel_mappings.data(), &error)};
387 if (error != OPUS_OK || decoder == nullptr) {
388 LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error);
389 IPC::ResponseBuilder rb{ctx, 2};
390 // TODO(ogniK): Use correct error code
391 rb.Push(ResultUnknown);
392 return;
393 }
394
395 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
396 rb.Push(ResultSuccess);
397 rb.PushIpcInterface<IHardwareOpusDecoderManager>(
398 system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
399}
400
357HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} { 401HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
358 static const FunctionInfo functions[] = { 402 static const FunctionInfo functions[] = {
359 {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"}, 403 {0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
@@ -362,7 +406,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
362 {3, nullptr, "GetWorkBufferSizeForMultiStream"}, 406 {3, nullptr, "GetWorkBufferSizeForMultiStream"},
363 {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"}, 407 {4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
364 {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"}, 408 {5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
365 {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"}, 409 {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx,
410 "OpenHardwareOpusDecoderForMultiStreamEx"},
366 {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"}, 411 {7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"},
367 {8, nullptr, "GetWorkBufferSizeExEx"}, 412 {8, nullptr, "GetWorkBufferSizeExEx"},
368 {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"}, 413 {9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"},
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
index ece65c02c..91d9998ac 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hwopus.h
@@ -18,8 +18,10 @@ struct OpusMultiStreamParametersEx {
18 u32 number_stereo_streams; 18 u32 number_stereo_streams;
19 u32 use_large_frame_size; 19 u32 use_large_frame_size;
20 u32 padding; 20 u32 padding;
21 std::array<u32, 64> channel_mappings; 21 std::array<u8, 0x100> channel_mappings;
22}; 22};
23static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,
24 "OpusMultiStreamParametersEx has incorrect size");
23 25
24class HwOpus final : public ServiceFramework<HwOpus> { 26class HwOpus final : public ServiceFramework<HwOpus> {
25public: 27public:
@@ -29,6 +31,7 @@ public:
29private: 31private:
30 void OpenHardwareOpusDecoder(HLERequestContext& ctx); 32 void OpenHardwareOpusDecoder(HLERequestContext& ctx);
31 void OpenHardwareOpusDecoderEx(HLERequestContext& ctx); 33 void OpenHardwareOpusDecoderEx(HLERequestContext& ctx);
34 void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx);
32 void GetWorkBufferSize(HLERequestContext& ctx); 35 void GetWorkBufferSize(HLERequestContext& ctx);
33 void GetWorkBufferSizeEx(HLERequestContext& ctx); 36 void GetWorkBufferSizeEx(HLERequestContext& ctx);
34 void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx); 37 void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx);
diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp
index 220cce28a..8d7da50fc 100644
--- a/src/video_core/host1x/codecs/codec.cpp
+++ b/src/video_core/host1x/codecs/codec.cpp
@@ -319,6 +319,7 @@ void Codec::Decode() {
319 LOG_WARNING(Service_NVDRV, "Zero width or height in frame"); 319 LOG_WARNING(Service_NVDRV, "Zero width or height in frame");
320 return; 320 return;
321 } 321 }
322 bool is_interlaced = initial_frame->interlaced_frame != 0;
322 if (av_codec_ctx->hw_device_ctx) { 323 if (av_codec_ctx->hw_device_ctx) {
323 final_frame = AVFramePtr{av_frame_alloc(), AVFrameDeleter}; 324 final_frame = AVFramePtr{av_frame_alloc(), AVFrameDeleter};
324 ASSERT_MSG(final_frame, "av_frame_alloc final_frame failed"); 325 ASSERT_MSG(final_frame, "av_frame_alloc final_frame failed");
@@ -334,7 +335,7 @@ void Codec::Decode() {
334 UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format); 335 UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format);
335 return; 336 return;
336 } 337 }
337 if (!final_frame->interlaced_frame) { 338 if (!is_interlaced) {
338 av_frames.push(std::move(final_frame)); 339 av_frames.push(std::move(final_frame));
339 } else { 340 } else {
340 if (!filters_initialized) { 341 if (!filters_initialized) {