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 ManualResetEvent _surfaceEvent;
|
||||||
private static long _surfacePtr;
|
private static long _surfacePtr;
|
||||||
|
private static long _window = 0;
|
||||||
|
|
||||||
public static VulkanLoader? VulkanLoader { get; private set; }
|
public static VulkanLoader? VulkanLoader { get; private set; }
|
||||||
|
|
||||||
@ -48,6 +49,9 @@ namespace LibRyujinx
|
|||||||
[DllImport("libryujinxjni")]
|
[DllImport("libryujinxjni")]
|
||||||
internal extern static void onFrameEnd(double time);
|
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);
|
public delegate IntPtr JniCreateSurface(IntPtr native_surface, IntPtr instance);
|
||||||
|
|
||||||
[UnmanagedCallersOnly(EntryPoint = "JNI_OnLoad")]
|
[UnmanagedCallersOnly(EntryPoint = "JNI_OnLoad")]
|
||||||
@ -236,9 +240,10 @@ namespace LibRyujinx
|
|||||||
}
|
}
|
||||||
|
|
||||||
[UnmanagedCallersOnly(EntryPoint = "Java_org_ryujinx_android_RyujinxNative_graphicsSetSurface")]
|
[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;
|
_surfacePtr = surfacePtr;
|
||||||
|
_window = window;
|
||||||
|
|
||||||
_surfaceEvent.Set();
|
_surfaceEvent.Set();
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,22 @@ namespace LibRyujinx
|
|||||||
|
|
||||||
while (device.ConsumeFrameAvailable())
|
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 IWindow Window => _window;
|
||||||
|
|
||||||
|
public SurfaceTransformFlagsKHR CurrentTransform => _window.CurrentTransform;
|
||||||
|
|
||||||
private readonly Func<Instance, Vk, SurfaceKHR> _getSurface;
|
private readonly Func<Instance, Vk, SurfaceKHR> _getSurface;
|
||||||
private readonly Func<string[]> _getRequiredExtensions;
|
private readonly Func<string[]> _getRequiredExtensions;
|
||||||
private readonly string _preferredGpuId;
|
private readonly string _preferredGpuId;
|
||||||
|
@ -132,6 +132,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
var oldSwapchain = _swapchain;
|
var oldSwapchain = _swapchain;
|
||||||
|
|
||||||
|
CurrentTransform = capabilities.CurrentTransform;
|
||||||
|
|
||||||
var swapchainCreateInfo = new SwapchainCreateInfoKHR
|
var swapchainCreateInfo = new SwapchainCreateInfoKHR
|
||||||
{
|
{
|
||||||
SType = StructureType.SwapchainCreateInfoKhr,
|
SType = StructureType.SwapchainCreateInfoKhr,
|
||||||
@ -143,7 +145,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
ImageUsage = ImageUsageFlags.ColorAttachmentBit | ImageUsageFlags.TransferDstBit | ImageUsageFlags.StorageBit,
|
ImageUsage = ImageUsageFlags.ColorAttachmentBit | ImageUsageFlags.TransferDstBit | ImageUsageFlags.StorageBit,
|
||||||
ImageSharingMode = SharingMode.Exclusive,
|
ImageSharingMode = SharingMode.Exclusive,
|
||||||
ImageArrayLayers = 1,
|
ImageArrayLayers = 1,
|
||||||
PreTransform = Ryujinx.Common.SystemInfo.SystemInfo.IsAndroid() ? SurfaceTransformFlagsKHR.IdentityBitKhr : capabilities.CurrentTransform,
|
PreTransform = capabilities.CurrentTransform,
|
||||||
CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha),
|
CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha),
|
||||||
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
|
PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled),
|
||||||
Clipped = true,
|
Clipped = true,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
@ -7,6 +8,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
public bool ScreenCaptureRequested { get; set; }
|
public bool ScreenCaptureRequested { get; set; }
|
||||||
|
|
||||||
|
public SurfaceTransformFlagsKHR CurrentTransform { get; set; }
|
||||||
|
|
||||||
public abstract void Dispose();
|
public abstract void Dispose();
|
||||||
public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback);
|
public abstract void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback);
|
||||||
public abstract void SetSize(int width, int height);
|
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 <cassert>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "libraries/adrenotools/include/adrenotools/driver.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
|
// A macro to pass call to Vulkan and check for return value for success
|
||||||
#define CALL_VK(func) \
|
#define CALL_VK(func) \
|
||||||
|
@ -52,7 +52,6 @@ extern "C"
|
|||||||
jobject instance,
|
jobject instance,
|
||||||
jobject surface) {
|
jobject surface) {
|
||||||
auto nativeWindow = ANativeWindow_fromSurface(env, surface);
|
auto nativeWindow = ANativeWindow_fromSurface(env, surface);
|
||||||
|
|
||||||
return nativeWindow == NULL ? -1 : (jlong) nativeWindow;
|
return nativeWindow == NULL ? -1 : (jlong) nativeWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,28 +66,6 @@ extern "C"
|
|||||||
ANativeWindow_release(nativeWindow);
|
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
|
JNIEXPORT void JNICALL
|
||||||
Java_org_ryujinx_android_NativeHelpers_attachCurrentThread(
|
Java_org_ryujinx_android_NativeHelpers_attachCurrentThread(
|
||||||
JNIEnv *env,
|
JNIEnv *env,
|
||||||
@ -192,6 +169,54 @@ void onFrameEnd(double time) {
|
|||||||
nano);
|
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"
|
extern "C"
|
||||||
JNIEXPORT jlong JNICALL
|
JNIEXPORT jlong JNICALL
|
||||||
Java_org_ryujinx_android_NativeHelpers_loadDriver(JNIEnv *env, jobject thiz,
|
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) {
|
Java_org_ryujinx_android_NativeHelpers_setTurboMode(JNIEnv *env, jobject thiz, jboolean enable) {
|
||||||
adrenotools_set_turbo(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 _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 var _nativeRyujinx: RyujinxNative = RyujinxNative()
|
private var _nativeRyujinx: RyujinxNative = RyujinxNative()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
holder.addCallback(this)
|
holder.addCallback(this)
|
||||||
|
|
||||||
|
nativeWindow = NativeWindow(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun surfaceCreated(holder: SurfaceHolder) {
|
override fun surfaceCreated(holder: SurfaceHolder) {
|
||||||
@ -38,9 +41,10 @@ class GameHost(context: Context?, private val mainViewModel: MainViewModel) : Su
|
|||||||
|
|
||||||
if(_width != width || _height != height)
|
if(_width != width || _height != height)
|
||||||
{
|
{
|
||||||
val nativeHelpers = NativeHelpers()
|
val window = nativeWindow.requeryWindowHandle()
|
||||||
val window = nativeHelpers.getNativeWindow(holder.surface)
|
_nativeRyujinx.graphicsSetSurface(window, nativeWindow.nativePointer)
|
||||||
_nativeRyujinx.graphicsSetSurface(window)
|
|
||||||
|
nativeWindow.swapInterval = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_width = width
|
_width = width
|
||||||
|
@ -9,14 +9,21 @@ class NativeHelpers {
|
|||||||
System.loadLibrary("ryujinxjni")
|
System.loadLibrary("ryujinxjni")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
external fun releaseNativeWindow(window:Long)
|
|
||||||
external fun createSurface(vkInstance:Long, window:Long) : 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 attachCurrentThread()
|
||||||
external fun detachCurrentThread()
|
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 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 inputSetButtonReleased(button: Int, id: Int)
|
||||||
external fun inputConnectGamepad(index: Int): Int
|
external fun inputConnectGamepad(index: Int): Int
|
||||||
external fun inputSetStickAxis(stick: Int, x: Float, y: Float, id: 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 deviceCloseEmulation()
|
||||||
external fun deviceSignalEmulationClose()
|
external fun deviceSignalEmulationClose()
|
||||||
external fun deviceGetDlcTitleId(path: String, ncaPath: String) : String
|
external fun deviceGetDlcTitleId(path: String, ncaPath: String) : String
|
||||||
|
Loading…
x
Reference in New Issue
Block a user