forked from MeloNX/MeloNX
android - replace surface pointer query with jni callback
This commit is contained in:
parent
5053ead4b3
commit
59c34f10aa
@ -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()),
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
Reference in New Issue
Block a user