forked from MeloNX/MeloNX
some optimizations. apply current transform to native window instead of defaulting to Identity
This commit is contained in:
parent
c732a9fbb6
commit
7a2fadb499
@ -30,6 +30,7 @@ namespace LibRyujinx
|
||||
{
|
||||
private static ManualResetEvent _surfaceEvent;
|
||||
private static long _surfacePtr;
|
||||
private static long _window = 0;
|
||||
|
||||
public static VulkanLoader? VulkanLoader { get; private set; }
|
||||
|
||||
@ -48,6 +49,9 @@ namespace LibRyujinx
|
||||
[DllImport("libryujinxjni")]
|
||||
internal extern static void onFrameEnd(double time);
|
||||
|
||||
[DllImport("libryujinxjni")]
|
||||
internal extern static void setCurrentTransform(long native_window, int transform);
|
||||
|
||||
public delegate IntPtr JniCreateSurface(IntPtr native_surface, IntPtr instance);
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "JNI_OnLoad")]
|
||||
@ -236,9 +240,10 @@ namespace LibRyujinx
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsSetSurface")]
|
||||
public static void JniSetSurface(JEnvRef jEnv, JObjectLocalRef jObj, JLong surfacePtr)
|
||||
public static void JniSetSurface(JEnvRef jEnv, JObjectLocalRef jObj, JLong surfacePtr, JLong window)
|
||||
{
|
||||
_surfacePtr = surfacePtr;
|
||||
_window = window;
|
||||
|
||||
_surfaceEvent.Set();
|
||||
}
|
||||
|
@ -185,7 +185,22 @@ namespace LibRyujinx
|
||||
|
||||
while (device.ConsumeFrameAvailable())
|
||||
{
|
||||
device.PresentFrame(() => _swapBuffersCallback?.Invoke());
|
||||
device.PresentFrame(() =>
|
||||
{
|
||||
VulkanRenderer? vk = device.Gpu.Renderer as VulkanRenderer;
|
||||
if(vk == null)
|
||||
{
|
||||
vk = (device.Gpu.Renderer as ThreadedRenderer)?.BaseRenderer as VulkanRenderer;
|
||||
}
|
||||
|
||||
if(vk != null)
|
||||
{
|
||||
var transform = vk.CurrentTransform;
|
||||
|
||||
setCurrentTransform(_window, (int)transform);
|
||||
}
|
||||
_swapBuffersCallback?.Invoke();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
public IWindow Window => _window;
|
||||
|
||||
public SurfaceTransformFlagsKHR CurrentTransform => _window.CurrentTransform;
|
||||
|
||||
private readonly Func<Instance, Vk, SurfaceKHR> _getSurface;
|
||||
private readonly Func<string[]> _getRequiredExtensions;
|
||||
private readonly string _preferredGpuId;
|
||||
|
@ -132,6 +132,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
|
||||
var oldSwapchain = _swapchain;
|
||||
|
||||
CurrentTransform = capabilities.CurrentTransform;
|
||||
|
||||
var swapchainCreateInfo = new SwapchainCreateInfoKHR
|
||||
{
|
||||
SType = StructureType.SwapchainCreateInfoKhr,
|
||||
@ -143,7 +145,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
ImageUsage = ImageUsageFlags.ColorAttachmentBit | ImageUsageFlags.TransferDstBit | ImageUsageFlags.StorageBit,
|
||||
ImageSharingMode = SharingMode.Exclusive,
|
||||
ImageArrayLayers = 1,
|
||||
PreTransform = Ryujinx.Common.SystemInfo.SystemInfo.IsAndroid() ? SurfaceTransformFlagsKHR.IdentityBitKhr : capabilities.CurrentTransform,
|
||||
PreTransform = capabilities.CurrentTransform,
|
||||
CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha),
|
||||
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
|
||||
Clipped = true,
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.Vulkan
|
||||
@ -7,6 +8,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||
{
|
||||
public bool ScreenCaptureRequested { get; set; }
|
||||
|
||||
public SurfaceTransformFlagsKHR CurrentTransform { get; set; }
|
||||
|
||||
public abstract void Dispose();
|
||||
public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback);
|
||||
public abstract void SetSize(int width, int height);
|
||||
|
305
src/RyujinxAndroid/app/src/main/cpp/native_window.h
Normal file
305
src/RyujinxAndroid/app/src/main/cpp/native_window.h
Normal file
@ -0,0 +1,305 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
// Copyright © 2021 The Android Open Source Project
|
||||
|
||||
#pragma once
|
||||
|
||||
/* A collection of various types from AOSP that allow us to access private APIs for Native Window which we utilize for emulating the guest SF more accurately */
|
||||
|
||||
/**
|
||||
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativebase/include/nativebase/nativebase.h;l=29;drc=cb496acbe593326e8d5d563847067d02b2df40ec
|
||||
*/
|
||||
#define ANDROID_NATIVE_UNSIGNED_CAST(x) static_cast<unsigned int>(x)
|
||||
|
||||
/**
|
||||
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativebase/include/nativebase/nativebase.h;l=34-38;drc=cb496acbe593326e8d5d563847067d02b2df40ec
|
||||
*/
|
||||
#define ANDROID_NATIVE_MAKE_CONSTANT(a, b, c, d) \
|
||||
((ANDROID_NATIVE_UNSIGNED_CAST(a) << 24) | \
|
||||
(ANDROID_NATIVE_UNSIGNED_CAST(b) << 16) | \
|
||||
(ANDROID_NATIVE_UNSIGNED_CAST(c) << 8) | \
|
||||
(ANDROID_NATIVE_UNSIGNED_CAST(d)))
|
||||
|
||||
/**
|
||||
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=60;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
|
||||
*/
|
||||
#define ANDROID_NATIVE_WINDOW_MAGIC ANDROID_NATIVE_MAKE_CONSTANT('_','w','n','d')
|
||||
|
||||
constexpr int AndroidNativeWindowMagic{ANDROID_NATIVE_WINDOW_MAGIC};
|
||||
|
||||
#undef ANDROID_NATIVE_WINDOW_MAGIC
|
||||
#undef ANDROID_NATIVE_MAKE_CONSTANT
|
||||
#undef ANDROID_NATIVE_UNSIGNED_CAST
|
||||
|
||||
/**
|
||||
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=325-331;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
|
||||
*/
|
||||
constexpr int64_t NativeWindowTimestampAuto{-9223372036854775807LL - 1};
|
||||
|
||||
/**
|
||||
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=198-259;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
|
||||
*/
|
||||
enum {
|
||||
NATIVE_WINDOW_CONNECT = 1, /* deprecated */
|
||||
NATIVE_WINDOW_DISCONNECT = 2, /* deprecated */
|
||||
NATIVE_WINDOW_SET_CROP = 3, /* private */
|
||||
NATIVE_WINDOW_SET_BUFFER_COUNT = 4,
|
||||
NATIVE_WINDOW_SET_BUFFERS_TRANSFORM = 6,
|
||||
NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP = 7,
|
||||
NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS = 8,
|
||||
NATIVE_WINDOW_SET_SCALING_MODE = 10, /* private */
|
||||
NATIVE_WINDOW_LOCK = 11, /* private */
|
||||
NATIVE_WINDOW_UNLOCK_AND_POST = 12, /* private */
|
||||
NATIVE_WINDOW_API_CONNECT = 13, /* private */
|
||||
NATIVE_WINDOW_API_DISCONNECT = 14, /* private */
|
||||
NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS = 15, /* private */
|
||||
NATIVE_WINDOW_SET_POST_TRANSFORM_CROP = 16, /* deprecated, unimplemented */
|
||||
NATIVE_WINDOW_SET_BUFFERS_STICKY_TRANSFORM = 17, /* private */
|
||||
NATIVE_WINDOW_SET_SIDEBAND_STREAM = 18,
|
||||
NATIVE_WINDOW_SET_BUFFERS_DATASPACE = 19,
|
||||
NATIVE_WINDOW_SET_SURFACE_DAMAGE = 20, /* private */
|
||||
NATIVE_WINDOW_SET_SHARED_BUFFER_MODE = 21,
|
||||
NATIVE_WINDOW_SET_AUTO_REFRESH = 22,
|
||||
NATIVE_WINDOW_GET_REFRESH_CYCLE_DURATION = 23,
|
||||
NATIVE_WINDOW_GET_NEXT_FRAME_ID = 24,
|
||||
NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS = 25,
|
||||
NATIVE_WINDOW_GET_COMPOSITOR_TIMING = 26,
|
||||
NATIVE_WINDOW_GET_FRAME_TIMESTAMPS = 27,
|
||||
NATIVE_WINDOW_GET_WIDE_COLOR_SUPPORT = 28,
|
||||
NATIVE_WINDOW_GET_HDR_SUPPORT = 29,
|
||||
NATIVE_WINDOW_GET_CONSUMER_USAGE64 = 31,
|
||||
NATIVE_WINDOW_SET_BUFFERS_SMPTE2086_METADATA = 32,
|
||||
NATIVE_WINDOW_SET_BUFFERS_CTA861_3_METADATA = 33,
|
||||
NATIVE_WINDOW_SET_BUFFERS_HDR10_PLUS_METADATA = 34,
|
||||
NATIVE_WINDOW_SET_AUTO_PREROTATION = 35,
|
||||
NATIVE_WINDOW_GET_LAST_DEQUEUE_START = 36, /* private */
|
||||
NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT = 37, /* private */
|
||||
NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */
|
||||
NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */
|
||||
NATIVE_WINDOW_SET_FRAME_RATE = 40,
|
||||
NATIVE_WINDOW_SET_CANCEL_INTERCEPTOR = 41, /* private */
|
||||
NATIVE_WINDOW_SET_DEQUEUE_INTERCEPTOR = 42, /* private */
|
||||
NATIVE_WINDOW_SET_PERFORM_INTERCEPTOR = 43, /* private */
|
||||
NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR = 44, /* private */
|
||||
NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */
|
||||
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */
|
||||
NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */
|
||||
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2 = 50, /* private */
|
||||
};
|
||||
|
||||
/**
|
||||
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativebase/include/nativebase/nativebase.h;l=43-56;drc=cb496acbe593326e8d5d563847067d02b2df40ec
|
||||
*/
|
||||
struct android_native_base_t {
|
||||
int magic;
|
||||
int version;
|
||||
void *reserved[4];
|
||||
|
||||
void (*incRef)(android_native_base_t *);
|
||||
|
||||
void (*decRef)(android_native_base_t *);
|
||||
};
|
||||
|
||||
/**
|
||||
* @url https://cs.android.com/android/platform/superproject/+/android11-release:frameworks/native/libs/nativewindow/include/system/window.h;l=341-560;drc=401cda638e7d17f6697b5a65c9a5ad79d056202d
|
||||
*/
|
||||
struct ANativeWindow {
|
||||
struct android_native_base_t common;
|
||||
|
||||
/* flags describing some attributes of this surface or its updater */
|
||||
const uint32_t flags;
|
||||
|
||||
/* min swap interval supported by this updated */
|
||||
const int minSwapInterval;
|
||||
|
||||
/* max swap interval supported by this updated */
|
||||
const int maxSwapInterval;
|
||||
|
||||
/* horizontal and vertical resolution in DPI */
|
||||
const float xdpi;
|
||||
const float ydpi;
|
||||
|
||||
/* Some storage reserved for the OEM's driver. */
|
||||
intptr_t oem[4];
|
||||
|
||||
/*
|
||||
* Set the swap interval for this surface.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*setSwapInterval)(struct ANativeWindow *window,
|
||||
int interval);
|
||||
|
||||
/*
|
||||
* Hook called by EGL to acquire a buffer. After this call, the buffer
|
||||
* is not locked, so its content cannot be modified. This call may block if
|
||||
* no buffers are available.
|
||||
*
|
||||
* The window holds a reference to the buffer between dequeueBuffer and
|
||||
* either queueBuffer or cancelBuffer, so clients only need their own
|
||||
* reference if they might use the buffer after queueing or canceling it.
|
||||
* Holding a reference to a buffer after queueing or canceling it is only
|
||||
* allowed if a specific buffer count has been set.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*
|
||||
* XXX: This function is deprecated. It will continue to work for some
|
||||
* time for binary compatibility, but the new dequeueBuffer function that
|
||||
* outputs a fence file descriptor should be used in its place.
|
||||
*/
|
||||
int (*dequeueBuffer_DEPRECATED)(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer **buffer);
|
||||
|
||||
/*
|
||||
* hook called by EGL to lock a buffer. This MUST be called before modifying
|
||||
* the content of a buffer. The buffer must have been acquired with
|
||||
* dequeueBuffer first.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*
|
||||
* XXX: This function is deprecated. It will continue to work for some
|
||||
* time for binary compatibility, but it is essentially a no-op, and calls
|
||||
* to it should be removed.
|
||||
*/
|
||||
int (*lockBuffer_DEPRECATED)(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer *buffer);
|
||||
|
||||
/*
|
||||
* Hook called by EGL when modifications to the render buffer are done.
|
||||
* This unlocks and post the buffer.
|
||||
*
|
||||
* The window holds a reference to the buffer between dequeueBuffer and
|
||||
* either queueBuffer or cancelBuffer, so clients only need their own
|
||||
* reference if they might use the buffer after queueing or canceling it.
|
||||
* Holding a reference to a buffer after queueing or canceling it is only
|
||||
* allowed if a specific buffer count has been set.
|
||||
*
|
||||
* Buffers MUST be queued in the same order than they were dequeued.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*
|
||||
* XXX: This function is deprecated. It will continue to work for some
|
||||
* time for binary compatibility, but the new queueBuffer function that
|
||||
* takes a fence file descriptor should be used in its place (pass a value
|
||||
* of -1 for the fence file descriptor if there is no valid one to pass).
|
||||
*/
|
||||
int (*queueBuffer_DEPRECATED)(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer *buffer);
|
||||
|
||||
/*
|
||||
* hook used to retrieve information about the native window.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*query)(const struct ANativeWindow *window,
|
||||
int what, int *value);
|
||||
|
||||
/*
|
||||
* hook used to perform various operations on the surface.
|
||||
* (*perform)() is a generic mechanism to add functionality to
|
||||
* ANativeWindow while keeping backward binary compatibility.
|
||||
*
|
||||
* DO NOT CALL THIS HOOK DIRECTLY. Instead, use the helper functions
|
||||
* defined below.
|
||||
*
|
||||
* (*perform)() returns -ENOENT if the 'what' parameter is not supported
|
||||
* by the surface's implementation.
|
||||
*
|
||||
* See above for a list of valid operations, such as
|
||||
* NATIVE_WINDOW_SET_USAGE or NATIVE_WINDOW_CONNECT
|
||||
*/
|
||||
int (*perform)(struct ANativeWindow *window,
|
||||
int operation, ...);
|
||||
|
||||
/*
|
||||
* Hook used to cancel a buffer that has been dequeued.
|
||||
* No synchronization is performed between dequeue() and cancel(), so
|
||||
* either external synchronization is needed, or these functions must be
|
||||
* called from the same thread.
|
||||
*
|
||||
* The window holds a reference to the buffer between dequeueBuffer and
|
||||
* either queueBuffer or cancelBuffer, so clients only need their own
|
||||
* reference if they might use the buffer after queueing or canceling it.
|
||||
* Holding a reference to a buffer after queueing or canceling it is only
|
||||
* allowed if a specific buffer count has been set.
|
||||
*
|
||||
* XXX: This function is deprecated. It will continue to work for some
|
||||
* time for binary compatibility, but the new cancelBuffer function that
|
||||
* takes a fence file descriptor should be used in its place (pass a value
|
||||
* of -1 for the fence file descriptor if there is no valid one to pass).
|
||||
*/
|
||||
int (*cancelBuffer_DEPRECATED)(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer *buffer);
|
||||
|
||||
/*
|
||||
* Hook called by EGL to acquire a buffer. This call may block if no
|
||||
* buffers are available.
|
||||
*
|
||||
* The window holds a reference to the buffer between dequeueBuffer and
|
||||
* either queueBuffer or cancelBuffer, so clients only need their own
|
||||
* reference if they might use the buffer after queueing or canceling it.
|
||||
* Holding a reference to a buffer after queueing or canceling it is only
|
||||
* allowed if a specific buffer count has been set.
|
||||
*
|
||||
* The libsync fence file descriptor returned in the int pointed to by the
|
||||
* fenceFd argument will refer to the fence that must signal before the
|
||||
* dequeued buffer may be written to. A value of -1 indicates that the
|
||||
* caller may access the buffer immediately without waiting on a fence. If
|
||||
* a valid file descriptor is returned (i.e. any value except -1) then the
|
||||
* caller is responsible for closing the file descriptor.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*dequeueBuffer)(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer **buffer, int *fenceFd);
|
||||
|
||||
/*
|
||||
* Hook called by EGL when modifications to the render buffer are done.
|
||||
* This unlocks and post the buffer.
|
||||
*
|
||||
* The window holds a reference to the buffer between dequeueBuffer and
|
||||
* either queueBuffer or cancelBuffer, so clients only need their own
|
||||
* reference if they might use the buffer after queueing or canceling it.
|
||||
* Holding a reference to a buffer after queueing or canceling it is only
|
||||
* allowed if a specific buffer count has been set.
|
||||
*
|
||||
* The fenceFd argument specifies a libsync fence file descriptor for a
|
||||
* fence that must signal before the buffer can be accessed. If the buffer
|
||||
* can be accessed immediately then a value of -1 should be used. The
|
||||
* caller must not use the file descriptor after it is passed to
|
||||
* queueBuffer, and the ANativeWindow implementation is responsible for
|
||||
* closing it.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*queueBuffer)(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer *buffer, int fenceFd);
|
||||
|
||||
/*
|
||||
* Hook used to cancel a buffer that has been dequeued.
|
||||
* No synchronization is performed between dequeue() and cancel(), so
|
||||
* either external synchronization is needed, or these functions must be
|
||||
* called from the same thread.
|
||||
*
|
||||
* The window holds a reference to the buffer between dequeueBuffer and
|
||||
* either queueBuffer or cancelBuffer, so clients only need their own
|
||||
* reference if they might use the buffer after queueing or canceling it.
|
||||
* Holding a reference to a buffer after queueing or canceling it is only
|
||||
* allowed if a specific buffer count has been set.
|
||||
*
|
||||
* The fenceFd argument specifies a libsync fence file decsriptor for a
|
||||
* fence that must signal before the buffer can be accessed. If the buffer
|
||||
* can be accessed immediately then a value of -1 should be used.
|
||||
*
|
||||
* Note that if the client has not waited on the fence that was returned
|
||||
* from dequeueBuffer, that same fence should be passed to cancelBuffer to
|
||||
* ensure that future uses of the buffer are preceded by a wait on that
|
||||
* fence. The caller must not use the file descriptor after it is passed
|
||||
* to cancelBuffer, and the ANativeWindow implementation is responsible for
|
||||
* closing it.
|
||||
*
|
||||
* Returns 0 on success or -errno on error.
|
||||
*/
|
||||
int (*cancelBuffer)(struct ANativeWindow *window,
|
||||
struct ANativeWindowBuffer *buffer, int fenceFd);
|
||||
};
|
@ -18,6 +18,7 @@
|
||||
#include <cassert>
|
||||
#include <fcntl.h>
|
||||
#include "libraries/adrenotools/include/adrenotools/driver.h"
|
||||
#include "native_window.h"
|
||||
|
||||
// A macro to pass call to Vulkan and check for return value for success
|
||||
#define CALL_VK(func) \
|
||||
|
@ -52,7 +52,6 @@ extern "C"
|
||||
jobject instance,
|
||||
jobject surface) {
|
||||
auto nativeWindow = ANativeWindow_fromSurface(env, surface);
|
||||
|
||||
return nativeWindow == NULL ? -1 : (jlong) nativeWindow;
|
||||
}
|
||||
|
||||
@ -67,28 +66,6 @@ extern "C"
|
||||
ANativeWindow_release(nativeWindow);
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_org_ryujinx_android_NativeHelpers_createSurface(
|
||||
JNIEnv *env,
|
||||
jobject instance,
|
||||
jlong vulkanInstance,
|
||||
jlong window) {
|
||||
auto nativeWindow = (ANativeWindow *) window;
|
||||
|
||||
if (nativeWindow != NULL)
|
||||
return -1;
|
||||
VkSurfaceKHR surface;
|
||||
auto vkInstance = VkInstance(vulkanInstance);
|
||||
auto fpCreateAndroidSurfaceKHR =
|
||||
reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(vkGetInstanceProcAddr(vkInstance, "vkCreateAndroidSurfaceKHR"));
|
||||
if (!fpCreateAndroidSurfaceKHR)
|
||||
return -1;
|
||||
VkAndroidSurfaceCreateInfoKHR info = { VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR };
|
||||
info.window = nativeWindow;
|
||||
VK_CHECK(fpCreateAndroidSurfaceKHR(vkInstance, &info, nullptr, &surface));
|
||||
return (jlong)surface;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_org_ryujinx_android_NativeHelpers_attachCurrentThread(
|
||||
JNIEnv *env,
|
||||
@ -192,6 +169,54 @@ void onFrameEnd(double time) {
|
||||
nano);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void setCurrentTransform(long native_window, int transform){
|
||||
if(native_window == 0 || native_window == -1)
|
||||
return;
|
||||
auto nativeWindow = (ANativeWindow *) native_window;
|
||||
|
||||
auto nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_IDENTITY;
|
||||
|
||||
transform = transform >> 1;
|
||||
|
||||
// transform is a valid VkSurfaceTransformFlagBitsKHR
|
||||
switch (transform) {
|
||||
case 0x1:
|
||||
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_IDENTITY;
|
||||
break;
|
||||
case 0x2:
|
||||
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_ROTATE_90;
|
||||
break;
|
||||
case 0x4:
|
||||
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_ROTATE_180;
|
||||
break;
|
||||
case 0x8:
|
||||
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_ROTATE_270;
|
||||
break;
|
||||
case 0x10:
|
||||
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL;
|
||||
break;
|
||||
case 0x20:
|
||||
nativeTransform = static_cast<ANativeWindowTransform>(
|
||||
ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_HORIZONTAL |
|
||||
ANATIVEWINDOW_TRANSFORM_ROTATE_90);
|
||||
break;
|
||||
case 0x40:
|
||||
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL;
|
||||
break;
|
||||
case 0x80:
|
||||
nativeTransform = static_cast<ANativeWindowTransform>(
|
||||
ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_MIRROR_VERTICAL |
|
||||
ANATIVEWINDOW_TRANSFORM_ROTATE_90);
|
||||
break;
|
||||
case 0x100:
|
||||
nativeTransform = ANativeWindowTransform::ANATIVEWINDOW_TRANSFORM_IDENTITY;
|
||||
break;
|
||||
}
|
||||
|
||||
nativeWindow->perform(nativeWindow, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM, static_cast<int32_t>(nativeTransform));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_org_ryujinx_android_NativeHelpers_loadDriver(JNIEnv *env, jobject thiz,
|
||||
@ -231,3 +256,30 @@ JNIEXPORT void JNICALL
|
||||
Java_org_ryujinx_android_NativeHelpers_setTurboMode(JNIEnv *env, jobject thiz, jboolean enable) {
|
||||
adrenotools_set_turbo(enable);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_ryujinx_android_NativeHelpers_getMaxSwapInterval(JNIEnv *env, jobject thiz,
|
||||
jlong native_window) {
|
||||
auto nativeWindow = (ANativeWindow *) native_window;
|
||||
|
||||
return nativeWindow->maxSwapInterval;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_ryujinx_android_NativeHelpers_getMinSwapInterval(JNIEnv *env, jobject thiz,
|
||||
jlong native_window) {
|
||||
auto nativeWindow = (ANativeWindow *) native_window;
|
||||
|
||||
return nativeWindow->minSwapInterval;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_org_ryujinx_android_NativeHelpers_setSwapInterval(JNIEnv *env, jobject thiz,
|
||||
jlong native_window, jint swap_interval) {
|
||||
auto nativeWindow = (ANativeWindow *) native_window;
|
||||
|
||||
return nativeWindow->setSwapInterval(nativeWindow, swap_interval);
|
||||
}
|
||||
|
@ -21,11 +21,14 @@ 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 var _nativeRyujinx: RyujinxNative = RyujinxNative()
|
||||
|
||||
init {
|
||||
holder.addCallback(this)
|
||||
|
||||
nativeWindow = NativeWindow(this)
|
||||
}
|
||||
|
||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||
@ -38,9 +41,10 @@ class GameHost(context: Context?, private val mainViewModel: MainViewModel) : Su
|
||||
|
||||
if(_width != width || _height != height)
|
||||
{
|
||||
val nativeHelpers = NativeHelpers()
|
||||
val window = nativeHelpers.getNativeWindow(holder.surface)
|
||||
_nativeRyujinx.graphicsSetSurface(window)
|
||||
val window = nativeWindow.requeryWindowHandle()
|
||||
_nativeRyujinx.graphicsSetSurface(window, nativeWindow.nativePointer)
|
||||
|
||||
nativeWindow.swapInterval = 0;
|
||||
}
|
||||
|
||||
_width = width
|
||||
|
@ -9,14 +9,21 @@ class NativeHelpers {
|
||||
System.loadLibrary("ryujinxjni")
|
||||
}
|
||||
}
|
||||
external fun releaseNativeWindow(window:Long)
|
||||
external fun createSurface(vkInstance:Long, window:Long) : Long
|
||||
external fun getCreateSurfacePtr() : Long
|
||||
external fun getNativeWindow(surface:Surface) : Long
|
||||
|
||||
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, privateAppsPath:String, driverName:String) : Long
|
||||
external fun loadDriver(
|
||||
nativeLibPath: String,
|
||||
privateAppsPath: String,
|
||||
driverName: String
|
||||
): Long
|
||||
|
||||
external fun setTurboMode(enable: Boolean)
|
||||
external fun getMaxSwapInterval(nativeWindow: Long): Int
|
||||
external fun getMinSwapInterval(nativeWindow: Long): Int
|
||||
external fun setSwapInterval(nativeWindow: Long, swapInterval: Int): Int
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
package org.ryujinx.android
|
||||
|
||||
import android.view.SurfaceView
|
||||
|
||||
class NativeWindow(val surface: SurfaceView) {
|
||||
var nativePointer: Long
|
||||
var nativeHelpers: NativeHelpers = NativeHelpers()
|
||||
private var _swapInterval : Int = 0
|
||||
|
||||
var maxSwapInterval : Int = 0
|
||||
get() {
|
||||
return if (nativePointer == -1L) 0 else nativeHelpers.getMaxSwapInterval(nativePointer)
|
||||
}
|
||||
|
||||
var minSwapInterval : Int = 0
|
||||
get() {
|
||||
return if (nativePointer == -1L) 0 else nativeHelpers.getMinSwapInterval(nativePointer)
|
||||
}
|
||||
|
||||
var swapInterval : Int
|
||||
get() {
|
||||
return _swapInterval
|
||||
}
|
||||
set(value) {
|
||||
if(nativePointer == -1L || nativeHelpers.setSwapInterval(nativePointer, value) == 0)
|
||||
_swapInterval = value
|
||||
}
|
||||
|
||||
init {
|
||||
nativePointer = nativeHelpers.getNativeWindow(surface.holder.surface);
|
||||
|
||||
swapInterval = maxOf(1, minSwapInterval)
|
||||
}
|
||||
|
||||
fun requeryWindowHandle() : Long {
|
||||
nativePointer = nativeHelpers.getNativeWindow(surface.holder.surface)
|
||||
|
||||
swapInterval = swapInterval
|
||||
|
||||
return nativePointer
|
||||
}
|
||||
}
|
@ -47,7 +47,7 @@ class RyujinxNative {
|
||||
external fun inputSetButtonReleased(button: Int, id: Int)
|
||||
external fun inputConnectGamepad(index: Int): Int
|
||||
external fun inputSetStickAxis(stick: Int, x: Float, y: Float, id: Int)
|
||||
external fun graphicsSetSurface(surface: Long)
|
||||
external fun graphicsSetSurface(surface: Long, window: Long)
|
||||
external fun deviceCloseEmulation()
|
||||
external fun deviceSignalEmulationClose()
|
||||
external fun deviceGetDlcTitleId(path: String, ncaPath: String) : String
|
||||
|
Loading…
x
Reference in New Issue
Block a user