1
0
forked from MeloNX/MeloNX

android - replace surface pointer query with jni callback

This commit is contained in:
Emmanuel Hansen 2024-09-10 08:36:27 +00:00
parent 5053ead4b3
commit 59c34f10aa
8 changed files with 76 additions and 75 deletions

View File

@ -29,7 +29,9 @@ namespace LibRyujinx.Android
("test", "()V"), ("test", "()V"),
("updateUiHandler", "(JJJIIIIJJ)V"), ("updateUiHandler", "(JJJIIIIJJ)V"),
("frameEnded", "()V"), ("frameEnded", "()V"),
("updateProgress", "(JF)V") ("updateProgress", "(JF)V"),
("getSurfacePtr", "()J"),
("getWindowHandle", "()J")
}; };
internal static void Initialize(JEnvRef jniEnv) internal static void Initialize(JEnvRef jniEnv)
@ -82,7 +84,7 @@ namespace LibRyujinx.Android
} }
} }
private static void CallMethod(string name, string descriptor, params JValue[] values) private static void CallVoidMethod(string name, string descriptor, params JValue[] values)
{ {
using var env = JniEnv.Create(); using var env = JniEnv.Create();
if (_methodCache.TryGetValue((name, descriptor), out var method)) if (_methodCache.TryGetValue((name, descriptor), out var method))
@ -94,26 +96,48 @@ namespace LibRyujinx.Android
} }
} }
private static JLong CallLongMethod(string name, string descriptor, params JValue[] values)
{
using var env = JniEnv.Create();
if (_methodCache.TryGetValue((name, descriptor), out var method))
{
if (descriptor.EndsWith("J"))
return JniHelper.CallStaticLongMethod(env.Env, (JClassLocalRef)(_classId.Value.Value), method, values) ?? (JLong)(-1);
}
return (JLong)(-1);
}
public static void Test() public static void Test()
{ {
CallMethod("test", "()V"); CallVoidMethod("test", "()V");
} }
public static void FrameEnded(double time) public static void FrameEnded(double time)
{ {
CallMethod("frameEnded", "()V"); CallVoidMethod("frameEnded", "()V");
} }
public static void UpdateProgress(string info, float progress) public static void UpdateProgress(string info, float progress)
{ {
using var infoPtr = new TempNativeString(info); using var infoPtr = new TempNativeString(info);
CallMethod("updateProgress", "(JF)V", new JValue[] CallVoidMethod("updateProgress", "(JF)V", new JValue[]
{ {
JValue.Create(infoPtr.AsBytes()), JValue.Create(infoPtr.AsBytes()),
JValue.Create(progress.AsBytes()) JValue.Create(progress.AsBytes())
}); });
} }
public static JLong GetSurfacePtr()
{
return CallLongMethod("getSurfacePtr", "()J");
}
public static JLong GetWindowsHandle()
{
return CallLongMethod("getWindowHandle", "()J");
}
public static void UpdateUiHandler(string newTitle, public static void UpdateUiHandler(string newTitle,
string newMessage, string newMessage,
string newWatermark, string newWatermark,
@ -129,7 +153,7 @@ namespace LibRyujinx.Android
using var watermarkPointer = new TempNativeString(newWatermark); using var watermarkPointer = new TempNativeString(newWatermark);
using var subtitlePointer = new TempNativeString(newSubtitle); using var subtitlePointer = new TempNativeString(newSubtitle);
using var newInitialPointer = new TempNativeString(newInitialText); using var newInitialPointer = new TempNativeString(newInitialText);
CallMethod("updateUiHandler", "(JJJIIIIJJ)V", new JValue[] CallVoidMethod("updateUiHandler", "(JJJIIIIJJ)V", new JValue[]
{ {
JValue.Create(titlePointer.AsBytes()), JValue.Create(titlePointer.AsBytes()),
JValue.Create(messagePointer.AsBytes()), JValue.Create(messagePointer.AsBytes()),

View File

@ -220,6 +220,20 @@ internal static class JniHelper
JObjectLocalRef jObject = callStaticObjectMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer); JObjectLocalRef jObject = callStaticObjectMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
return !JniHelper.ExceptionCheck(jEnv) ? jObject : null; return !JniHelper.ExceptionCheck(jEnv) ? jObject : null;
} }
public static JLong? CallStaticLongMethod(JEnvRef jEnv, JClassLocalRef jClass, JMethodId jMethodId,
params JValue[] args)
{
ref readonly JEnvValue value = ref jEnv.Environment;
ref JNativeInterface jInterface = ref value.Functions;
IntPtr callStaticLongMethodPtr = jInterface.CallStaticLongMethodAPointer;
CallStaticLongMethodADelegate callStaticLongMethod =
callStaticLongMethodPtr.GetUnsafeDelegate<CallStaticLongMethodADelegate>()!;
using IReadOnlyFixedMemory<JValue>.IDisposable fArgs = args.AsMemory().GetFixedContext();
JLong jLong = callStaticLongMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
return !JniHelper.ExceptionCheck(jEnv) ? jLong : null;
}
public static void CallVoidMethod(JEnvRef jEnv, JObjectLocalRef jObject, JMethodId jMethodId, params JValue[] args) public static void CallVoidMethod(JEnvRef jEnv, JObjectLocalRef jObject, JMethodId jMethodId, params JValue[] args)
{ {
ref readonly JEnvValue value = ref jEnv.Environment; ref readonly JEnvValue value = ref jEnv.Environment;

View File

@ -21,7 +21,6 @@ namespace LibRyujinx
{ {
public static partial class LibRyujinx public static partial class LibRyujinx
{ {
private static ManualResetEvent _surfaceEvent;
private static long _surfacePtr; private static long _surfacePtr;
private static long _window = 0; private static long _window = 0;
@ -59,10 +58,6 @@ namespace LibRyujinx
Interop.Test(); Interop.Test();
_surfaceEvent?.Set();
_surfaceEvent = new ManualResetEvent(false);
return init; return init;
} }
@ -259,16 +254,6 @@ namespace LibRyujinx
}); });
} }
[UnmanagedCallersOnly(EntryPoint = "graphicsSetSurface")]
public static void JniSetSurface(long surfacePtr, long window)
{
Logger.Trace?.Print(LogClass.Application, "Jni Function Call");
_surfacePtr = surfacePtr;
_window = window;
_surfaceEvent.Set();
}
[UnmanagedCallersOnly(EntryPoint = "graphicsInitializeRenderer")] [UnmanagedCallersOnly(EntryPoint = "graphicsInitializeRenderer")]
public unsafe static bool JnaGraphicsInitializeRenderer(char** extensionsArray, public unsafe static bool JnaGraphicsInitializeRenderer(char** extensionsArray,
int extensionsLength, int extensionsLength,
@ -294,8 +279,8 @@ namespace LibRyujinx
CreateSurface createSurfaceFunc = instance => CreateSurface createSurfaceFunc = instance =>
{ {
_surfaceEvent.WaitOne(); _surfacePtr = Interop.GetSurfacePtr();
_surfaceEvent.Reset(); _window = Interop.GetWindowsHandle();
var api = VulkanLoader?.GetApi() ?? Vk.GetApi(); var api = VulkanLoader?.GetApi() ?? Vk.GetApi();
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension)) if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))

View File

@ -21,29 +21,9 @@
#include <chrono> #include <chrono>
#include <csignal> #include <csignal>
JNIEnv *_rendererEnv = nullptr;
std::chrono::time_point<std::chrono::steady_clock, std::chrono::nanoseconds> _currentTimePoint; std::chrono::time_point<std::chrono::steady_clock, std::chrono::nanoseconds> _currentTimePoint;
JNIEnv *getEnv(bool isRenderer) {
JNIEnv *env;
if (isRenderer) {
env = _rendererEnv;
}
if (env != nullptr)
return env;
auto result = _vm->AttachCurrentThread(&env, NULL);
return env;
}
void detachEnv() {
auto result = _vm->DetachCurrentThread();
}
extern "C" extern "C"
{ {
JNIEXPORT jlong JNICALL JNIEXPORT jlong JNICALL
@ -66,28 +46,6 @@ Java_org_ryujinx_android_NativeHelpers_releaseNativeWindow(
ANativeWindow_release(nativeWindow); ANativeWindow_release(nativeWindow);
} }
JNIEXPORT void JNICALL
Java_org_ryujinx_android_NativeHelpers_attachCurrentThread(
JNIEnv *env,
jobject instance) {
JavaVM *jvm = NULL;
env->GetJavaVM(&jvm);
if (jvm != NULL)
jvm->AttachCurrentThread(&env, NULL);
}
JNIEXPORT void JNICALL
Java_org_ryujinx_android_NativeHelpers_detachCurrentThread(
JNIEnv *env,
jobject instance) {
JavaVM *jvm = NULL;
env->GetJavaVM(&jvm);
if (jvm != NULL)
jvm->DetachCurrentThread();
}
long createSurface(long native_surface, long instance) { long createSurface(long native_surface, long instance) {
auto nativeWindow = (ANativeWindow *) native_surface; auto nativeWindow = (ANativeWindow *) native_surface;
VkSurfaceKHR surface; VkSurfaceKHR surface;

View File

@ -12,6 +12,7 @@ import kotlin.concurrent.thread
@SuppressLint("ViewConstructor") @SuppressLint("ViewConstructor")
class GameHost(context: Context?, private val mainViewModel: MainViewModel) : SurfaceView(context), class GameHost(context: Context?, private val mainViewModel: MainViewModel) : SurfaceView(context),
SurfaceHolder.Callback { SurfaceHolder.Callback {
private var _currentWindow: Long = -1
private var isProgressHidden: Boolean = false private var isProgressHidden: Boolean = false
private var progress: MutableState<String>? = null private var progress: MutableState<String>? = null
private var progressValue: MutableState<Float>? = null private var progressValue: MutableState<Float>? = null
@ -25,12 +26,22 @@ class GameHost(context: Context?, private val mainViewModel: MainViewModel) : Su
private var _guestThread: Thread? = null private var _guestThread: Thread? = null
private var _isInit: Boolean = false private var _isInit: Boolean = false
private var _isStarted: Boolean = false private var _isStarted: Boolean = false
private val nativeWindow: NativeWindow private val _nativeWindow: NativeWindow
val currentSurface:Long
get() {
return _currentWindow
}
val currentWindowhandle: Long
get() {
return _nativeWindow.nativePointer
}
init { init {
holder.addCallback(this) holder.addCallback(this)
nativeWindow = NativeWindow(this) _nativeWindow = NativeWindow(this)
mainViewModel.gameHost = this mainViewModel.gameHost = this
} }
@ -53,18 +64,18 @@ class GameHost(context: Context?, private val mainViewModel: MainViewModel) : Su
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
if (_isClosed) if (_isClosed)
return return
start(holder)
if (_width != width || _height != height) { if (_width != width || _height != height) {
val window = nativeWindow.requeryWindowHandle() _currentWindow = _nativeWindow.requeryWindowHandle()
RyujinxNative.jnaInstance.graphicsSetSurface(window, nativeWindow.nativePointer)
nativeWindow.swapInterval = 0 _nativeWindow.swapInterval = 0
} }
_width = width _width = width
_height = height _height = height
start(holder)
RyujinxNative.jnaInstance.graphicsRendererSetSize( RyujinxNative.jnaInstance.graphicsRendererSetSize(
width, width,
height height

View File

@ -15,8 +15,6 @@ class NativeHelpers {
external fun releaseNativeWindow(window: Long) external fun releaseNativeWindow(window: Long)
external fun getCreateSurfacePtr(): Long external fun getCreateSurfacePtr(): Long
external fun getNativeWindow(surface: Surface): Long external fun getNativeWindow(surface: Surface): Long
external fun attachCurrentThread()
external fun detachCurrentThread()
external fun loadDriver( external fun loadDriver(
nativeLibPath: String, nativeLibPath: String,

View File

@ -58,7 +58,6 @@ interface RyujinxNativeJna : Library {
fun inputSetStickAxis(stick: Int, x: Float, y: Float, id: Int) fun inputSetStickAxis(stick: Int, x: Float, y: Float, id: Int)
fun inputSetAccelerometerData(x: Float, y: Float, z: Float, id: Int) fun inputSetAccelerometerData(x: Float, y: Float, z: Float, id: Int)
fun inputSetGyroData(x: Float, y: Float, z: Float, id: Int) fun inputSetGyroData(x: Float, y: Float, z: Float, id: Int)
fun graphicsSetSurface(surface: Long, window: Long)
fun deviceCloseEmulation() fun deviceCloseEmulation()
fun deviceSignalEmulationClose() fun deviceSignalEmulationClose()
fun userGetOpenedUser(): String fun userGetOpenedUser(): String
@ -104,6 +103,18 @@ class RyujinxNative {
MainActivity.frameEnded() MainActivity.frameEnded()
} }
@JvmStatic
fun getSurfacePtr() : Long
{
return MainActivity.mainViewModel?.gameHost?.currentSurface ?: -1
}
@JvmStatic
fun getWindowHandle() : Long
{
return MainActivity.mainViewModel?.gameHost?.currentWindowhandle ?: -1
}
@JvmStatic @JvmStatic
fun updateProgress(infoPtr : Long, progress: Float) fun updateProgress(infoPtr : Long, progress: Float)
{ {

View File

@ -24,7 +24,7 @@ android.nonTransitiveRClass=true
# Build configuration # Build configuration
# It needs to be set to either "debug" or "release" and can also be overriden on a per build basis # It needs to be set to either "debug" or "release" and can also be overriden on a per build basis
# by adding -Dorg.ryujinx.config=NAME to the command line. # by adding -Dorg.ryujinx.config=NAME to the command line.
org.ryujinx.config=debug org.ryujinx.config=release
# Controls stripping of symbols from libryujinx # Controls stripping of symbols from libryujinx
# Setting this property to auto causes symbols to be stripped for release builds, # Setting this property to auto causes symbols to be stripped for release builds,
# but not for debug builds. # but not for debug builds.