Archived
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"),
("updateUiHandler", "(JJJIIIIJJ)V"),
("frameEnded", "()V"),
("updateProgress", "(JF)V")
("updateProgress", "(JF)V"),
("getSurfacePtr", "()J"),
("getWindowHandle", "()J")
};
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();
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()
{
CallMethod("test", "()V");
CallVoidMethod("test", "()V");
}
public static void FrameEnded(double time)
{
CallMethod("frameEnded", "()V");
CallVoidMethod("frameEnded", "()V");
}
public static void UpdateProgress(string info, float progress)
{
using var infoPtr = new TempNativeString(info);
CallMethod("updateProgress", "(JF)V", new JValue[]
CallVoidMethod("updateProgress", "(JF)V", new JValue[]
{
JValue.Create(infoPtr.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,
string newMessage,
string newWatermark,
@ -129,7 +153,7 @@ namespace LibRyujinx.Android
using var watermarkPointer = new TempNativeString(newWatermark);
using var subtitlePointer = new TempNativeString(newSubtitle);
using var newInitialPointer = new TempNativeString(newInitialText);
CallMethod("updateUiHandler", "(JJJIIIIJJ)V", new JValue[]
CallVoidMethod("updateUiHandler", "(JJJIIIIJJ)V", new JValue[]
{
JValue.Create(titlePointer.AsBytes()),
JValue.Create(messagePointer.AsBytes()),

View File

@ -220,6 +220,20 @@ internal static class JniHelper
JObjectLocalRef jObject = callStaticObjectMethod(jEnv, jClass, jMethodId, fArgs.ValuePointer);
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)
{
ref readonly JEnvValue value = ref jEnv.Environment;

View File

@ -21,7 +21,6 @@ namespace LibRyujinx
{
public static partial class LibRyujinx
{
private static ManualResetEvent _surfaceEvent;
private static long _surfacePtr;
private static long _window = 0;
@ -59,10 +58,6 @@ namespace LibRyujinx
Interop.Test();
_surfaceEvent?.Set();
_surfaceEvent = new ManualResetEvent(false);
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")]
public unsafe static bool JnaGraphicsInitializeRenderer(char** extensionsArray,
int extensionsLength,
@ -294,8 +279,8 @@ namespace LibRyujinx
CreateSurface createSurfaceFunc = instance =>
{
_surfaceEvent.WaitOne();
_surfaceEvent.Reset();
_surfacePtr = Interop.GetSurfacePtr();
_window = Interop.GetWindowsHandle();
var api = VulkanLoader?.GetApi() ?? Vk.GetApi();
if (api.TryGetInstanceExtension(new Instance(instance), out KhrAndroidSurface surfaceExtension))

View File

@ -21,29 +21,9 @@
#include <chrono>
#include <csignal>
JNIEnv *_rendererEnv = nullptr;
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"
{
JNIEXPORT jlong JNICALL
@ -66,28 +46,6 @@ Java_org_ryujinx_android_NativeHelpers_releaseNativeWindow(
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) {
auto nativeWindow = (ANativeWindow *) native_surface;
VkSurfaceKHR surface;

View File

@ -12,6 +12,7 @@ import kotlin.concurrent.thread
@SuppressLint("ViewConstructor")
class GameHost(context: Context?, private val mainViewModel: MainViewModel) : SurfaceView(context),
SurfaceHolder.Callback {
private var _currentWindow: Long = -1
private var isProgressHidden: Boolean = false
private var progress: MutableState<String>? = 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 _isInit: 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 {
holder.addCallback(this)
nativeWindow = NativeWindow(this)
_nativeWindow = NativeWindow(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) {
if (_isClosed)
return
start(holder)
if (_width != width || _height != height) {
val window = nativeWindow.requeryWindowHandle()
RyujinxNative.jnaInstance.graphicsSetSurface(window, nativeWindow.nativePointer)
_currentWindow = _nativeWindow.requeryWindowHandle()
nativeWindow.swapInterval = 0
_nativeWindow.swapInterval = 0
}
_width = width
_height = height
start(holder)
RyujinxNative.jnaInstance.graphicsRendererSetSize(
width,
height

View File

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

View File

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

View File

@ -24,7 +24,7 @@ android.nonTransitiveRClass=true
# Build configuration
# 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.
org.ryujinx.config=debug
org.ryujinx.config=release
# Controls stripping of symbols from libryujinx
# Setting this property to auto causes symbols to be stripped for release builds,
# but not for debug builds.