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"),
|
("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()),
|
||||||
|
@ -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;
|
||||||
|
@ -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))
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user