mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2026-04-23 02:57:31 -04:00
Add integrated Turnip driver + loader
Also adds an override so you can turn it off when you have your own, good-working system Vulkan driver
This commit is contained in:
@@ -60,6 +60,7 @@ public class LauncherPreferences {
|
||||
public static boolean PREF_DUMP_SHADERS = false;
|
||||
public static float PREF_DEADZONE_SCALE = 1f;
|
||||
public static boolean PREF_BIG_CORE_AFFINITY = false;
|
||||
public static boolean PREF_ZINK_PREFER_SYSTEM_DRIVER = false;
|
||||
|
||||
|
||||
|
||||
@@ -103,6 +104,7 @@ public class LauncherPreferences {
|
||||
PREF_DUMP_SHADERS = DEFAULT_PREF.getBoolean("dump_shaders", false);
|
||||
PREF_DEADZONE_SCALE = DEFAULT_PREF.getInt("gamepad_deadzone_scale", 100)/100f;
|
||||
PREF_BIG_CORE_AFFINITY = DEFAULT_PREF.getBoolean("bigCoreAffinity", false);
|
||||
PREF_ZINK_PREFER_SYSTEM_DRIVER = DEFAULT_PREF.getBoolean("zinkPreferSystemDriver", false);
|
||||
|
||||
String argLwjglLibname = "-Dorg.lwjgl.opengl.libname=";
|
||||
for (String arg : JREUtils.parseJavaArguments(PREF_CUSTOM_JAVA_ARGS)) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import static net.kdt.pojavlaunch.Tools.NATIVE_LIB_DIR;
|
||||
import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics;
|
||||
import static net.kdt.pojavlaunch.Tools.shareLog;
|
||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_DUMP_SHADERS;
|
||||
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_ZINK_PREFER_SYSTEM_DRIVER;
|
||||
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
@@ -184,6 +185,8 @@ public class JREUtils {
|
||||
|
||||
if(PREF_DUMP_SHADERS)
|
||||
envMap.put("LIBGL_VGPU_DUMP", "1");
|
||||
if(PREF_ZINK_PREFER_SYSTEM_DRIVER)
|
||||
envMap.put("POJAV_ZINK_PREFER_SYSTEM_DRIVER", "1");
|
||||
|
||||
|
||||
// The OPEN GL version is changed according
|
||||
@@ -444,7 +447,7 @@ public class JREUtils {
|
||||
case "opengles2_5":
|
||||
case "opengles3":
|
||||
renderLibrary = "libgl4es_114.so"; break;
|
||||
case "vulkan_zink": renderLibrary = "libOSMesa_8.so"; break;
|
||||
case "vulkan_zink": renderLibrary = "libOSMesa.so"; break;
|
||||
case "opengles3_desktopgl_angle_vulkan" : renderLibrary = "libtinywrapper.so"; break;
|
||||
default:
|
||||
Log.w("RENDER_LIBRARY", "No renderer selected, defaulting to opengles2");
|
||||
|
||||
@@ -51,9 +51,23 @@ LOCAL_SRC_FILES := \
|
||||
environ/environ.c \
|
||||
input_bridge_v3.c \
|
||||
jre_launcher.c \
|
||||
utils.c
|
||||
utils.c \
|
||||
driver_helper/nsbypass.c
|
||||
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
|
||||
LOCAL_CFLAGS += -DADRENO_POSSIBLE
|
||||
LOCAL_LDLIBS += -lEGL -lGLESv2
|
||||
endif
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
#ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := linkerhook
|
||||
LOCAL_SRC_FILES := driver_helper/hook.c
|
||||
LOCAL_LDFLAGS := -z global
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
#endif
|
||||
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := istdio
|
||||
LOCAL_SHARED_LIBRARIES := xhook
|
||||
|
||||
@@ -21,7 +21,7 @@ void (*glReadPixels_p) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
||||
void dlsym_OSMesa() {
|
||||
char* main_path = NULL;
|
||||
char* alt_path = NULL;
|
||||
if(asprintf(&main_path, "%s/libOSMesa_8.so", getenv("POJAV_NATIVEDIR")) == -1 ||
|
||||
if(asprintf(&main_path, "%s/libOSMesa.so", getenv("POJAV_NATIVEDIR")) == -1 ||
|
||||
asprintf(&alt_path, "%s/libOSMesa.so.8", getenv("POJAV_NATIVEDIR")) == -1) {
|
||||
abort();
|
||||
}
|
||||
|
||||
43
app_pojavlauncher/src/main/jni/driver_helper/hook.c
Normal file
43
app_pojavlauncher/src/main/jni/driver_helper/hook.c
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Created by maks on 05.06.2023.
|
||||
//
|
||||
#include <android/dlext.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef void* (*android_dlopen_ext_t)(const char *filename, int flags, const android_dlextinfo *extinfo);
|
||||
typedef struct android_namespace_t* (*android_get_exported_namespace_t)(const char* name);
|
||||
|
||||
static void* ready_handle;
|
||||
static android_dlopen_ext_t original_func;
|
||||
static android_get_exported_namespace_t android_get_exported_namespace;
|
||||
|
||||
static const char *sphal_namespaces[3] = {
|
||||
"sphal", "vendor", "default"
|
||||
};
|
||||
|
||||
|
||||
__attribute__((visibility("default"))) void app__pojav_linkerhook_set_data(void* data, void* data1, void* data2) {
|
||||
ready_handle = data;
|
||||
original_func = data1;
|
||||
android_get_exported_namespace = data2;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void *android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo) {
|
||||
if(!strstr(filename, "vulkan."))
|
||||
return original_func(filename, flags, extinfo);
|
||||
return ready_handle;
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void *android_load_sphal_library(const char *filename, int flags) {
|
||||
if(strstr(filename, "vulkan.")) return ready_handle;
|
||||
struct android_namespace_t* androidNamespace;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
androidNamespace = android_get_exported_namespace(sphal_namespaces[i]);
|
||||
if(androidNamespace != NULL) break;
|
||||
}
|
||||
android_dlextinfo info;
|
||||
info.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||
info.library_namespace = androidNamespace;
|
||||
return original_func(filename, flags, &info);
|
||||
}
|
||||
165
app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c
Normal file
165
app_pojavlauncher/src/main/jni/driver_helper/nsbypass.c
Normal file
@@ -0,0 +1,165 @@
|
||||
//
|
||||
// Created by maks on 05.06.2023.
|
||||
//
|
||||
#include "nsbypass.h"
|
||||
#include <dlfcn.h>
|
||||
#include <android/dlext.h>
|
||||
#include <android/log.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/user.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/limits.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <elf.h>
|
||||
|
||||
/* upper 6 bits of an ARM64 instruction are the instruction name */
|
||||
#define OP_MS 0b11111100000000000000000000000000
|
||||
/* Branch Label instruction opcode and immediate mask */
|
||||
#define BL_OP 0b10010100000000000000000000000000
|
||||
#define BL_IM 0b00000011111111111111111111111111
|
||||
/* Library search path */
|
||||
#define SEARCH_PATH "/system/lib64"
|
||||
#define ELF_EHDR Elf64_Ehdr
|
||||
#define ELF_SHDR Elf64_Shdr
|
||||
#define ELF_HALF Elf64_Half
|
||||
#define ELF_XWORD Elf64_Xword
|
||||
#define ELF_DYN Elf64_Dyn
|
||||
|
||||
//#define ADRENO_POSSIBLE
|
||||
|
||||
typedef void* (*loader_dlopen_t)(const char* filename, int flags, const void* caller_addr);
|
||||
|
||||
typedef struct android_namespace_t* (*ld_android_create_namespace_t)(
|
||||
const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
|
||||
const char* permitted_when_isolated_path, struct android_namespace_t* parent, const void* caller_addr);
|
||||
|
||||
typedef struct android_namespace_t* (*ld_android_get_exported_namespace_t)(const char* name, const void* caller_addr);
|
||||
|
||||
static ld_android_create_namespace_t android_create_namespace;
|
||||
static ld_android_get_exported_namespace_t android_get_exported_namespace;
|
||||
static struct android_namespace_t* namespace;
|
||||
|
||||
struct android_namespace_t* local_android_create_namespace(
|
||||
const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
|
||||
const char* permitted_when_isolated_path, struct android_namespace_t* parent) {
|
||||
void* caller = __builtin_return_address(0);
|
||||
return android_create_namespace(name, ld_library_path, default_library_path, type, permitted_when_isolated_path, parent, caller);
|
||||
}
|
||||
|
||||
struct android_namespace_t* ns_android_get_exported_namespace(
|
||||
const char* name) {
|
||||
void* caller = __builtin_return_address(0);
|
||||
return android_get_exported_namespace(name, caller);
|
||||
}
|
||||
|
||||
|
||||
bool linker_ns_load(const char* lib_search_path) {
|
||||
#ifndef ADRENO_POSSIBLE
|
||||
return false;
|
||||
#endif
|
||||
uint32_t *dlext_bl_addr = (uint32_t*)&dlopen;
|
||||
while((*dlext_bl_addr & OP_MS) !=
|
||||
BL_OP) dlext_bl_addr++; //walk through the function until we find the label that we need to go to
|
||||
__android_log_print(ANDROID_LOG_INFO, "nsbypass", "found branch label: %u", *dlext_bl_addr);
|
||||
loader_dlopen_t loader_dlopen;
|
||||
loader_dlopen = (loader_dlopen_t)(((char *) dlext_bl_addr) + (*dlext_bl_addr & BL_IM)*4);
|
||||
mprotect(loader_dlopen, PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC); // reprotecting the function removes protection from indirect jumps
|
||||
void* ld_android_handle = loader_dlopen("ld-android.so", RTLD_LAZY, &dlopen);
|
||||
__android_log_print(ANDROID_LOG_INFO, "nsbypass", "ld-android.so handle: %p", ld_android_handle);
|
||||
if(ld_android_handle == NULL) return false;
|
||||
android_create_namespace = dlsym(ld_android_handle, "__loader_android_create_namespace");
|
||||
android_get_exported_namespace = dlsym(ld_android_handle, "__loader_android_get_exported_namespace");
|
||||
if(android_create_namespace == NULL || android_get_exported_namespace == NULL) {
|
||||
dlclose(ld_android_handle);
|
||||
return false;
|
||||
}
|
||||
char full_path[strlen(SEARCH_PATH) + strlen(lib_search_path) + 2 + 1];
|
||||
sprintf(full_path, "%s:%s", SEARCH_PATH, lib_search_path);
|
||||
namespace = local_android_create_namespace("pojav-driver",
|
||||
full_path,
|
||||
full_path,
|
||||
3 /* TYPE_SHAFED | TYPE_ISOLATED */,
|
||||
"/system/:/data/:/vendor/:/apex/", NULL);
|
||||
//dlclose(ld_android_handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
void* linker_ns_dlopen(const char* name, int flag) {
|
||||
#ifndef ADRENO_POSSIBLE
|
||||
return NULL;
|
||||
#endif
|
||||
android_dlextinfo dlextinfo;
|
||||
dlextinfo.flags = ANDROID_DLEXT_USE_NAMESPACE;
|
||||
dlextinfo.library_namespace = namespace;
|
||||
return android_dlopen_ext(name, flag, &dlextinfo);
|
||||
}
|
||||
|
||||
bool patch_elf_soname(int patchfd, int realfd, uint16_t patchid) {
|
||||
struct stat realstat;
|
||||
if(fstat(realfd, &realstat)) return false;
|
||||
if(ftruncate(patchfd, realstat.st_size) == -1) return false;
|
||||
char* target = mmap(NULL, realstat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, patchfd, 0);
|
||||
if(!target) return false;
|
||||
if(read(realfd, target, realstat.st_size) != realstat.st_size) {
|
||||
munmap(target, realstat.st_size);
|
||||
return false;
|
||||
}
|
||||
close(realfd);
|
||||
|
||||
|
||||
ELF_EHDR *ehdr = (ELF_EHDR*)target;
|
||||
ELF_SHDR *shdr = (ELF_SHDR*)(target + ehdr->e_shoff);
|
||||
for(ELF_HALF i = 0; i < ehdr->e_shnum; i++) {
|
||||
ELF_SHDR *hdr = &shdr[i];
|
||||
if(hdr->sh_type == SHT_DYNAMIC) {
|
||||
char* strtab = target + shdr[hdr->sh_link].sh_offset;
|
||||
ELF_DYN *dynEntries = (ELF_DYN*)(target + hdr->sh_offset);
|
||||
for(ELF_XWORD k = 0; k < (hdr->sh_size / hdr->sh_entsize);k++) {
|
||||
ELF_DYN* dynEntry = &dynEntries[k];
|
||||
if(dynEntry->d_tag == DT_SONAME) {
|
||||
char* soname = strtab + dynEntry->d_un.d_val;
|
||||
char sprb[4];
|
||||
snprintf(sprb, 4, "%03x", patchid);
|
||||
memcpy(soname, sprb, 3);
|
||||
munmap(target, realstat.st_size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flags) {
|
||||
#ifndef ADRENO_POSSIBLE
|
||||
return NULL;
|
||||
#endif
|
||||
char pathbuf[PATH_MAX];
|
||||
static uint16_t patch_id;
|
||||
int patch_fd, real_fd;
|
||||
snprintf(pathbuf,PATH_MAX,"%s/%d_p.so", tmpdir, patch_id);
|
||||
patch_fd = open(pathbuf, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if(patch_fd == -1) return NULL;
|
||||
snprintf(pathbuf,PATH_MAX,"%s/%s", SEARCH_PATH, name);
|
||||
real_fd = open(pathbuf, O_RDONLY);
|
||||
if(real_fd == -1) {
|
||||
close(patch_fd);
|
||||
return NULL;
|
||||
}
|
||||
if(!patch_elf_soname(patch_fd, real_fd, patch_id)) {
|
||||
close(patch_fd);
|
||||
close(real_fd);
|
||||
return NULL;
|
||||
}
|
||||
android_dlextinfo extinfo;
|
||||
extinfo.flags = ANDROID_DLEXT_USE_NAMESPACE | ANDROID_DLEXT_USE_LIBRARY_FD;
|
||||
extinfo.library_fd = patch_fd;
|
||||
extinfo.library_namespace = namespace;
|
||||
snprintf(pathbuf, PATH_MAX, "/proc/self/fd/%d", patch_fd);
|
||||
return android_dlopen_ext(pathbuf, flags, &extinfo);
|
||||
}
|
||||
16
app_pojavlauncher/src/main/jni/driver_helper/nsbypass.h
Normal file
16
app_pojavlauncher/src/main/jni/driver_helper/nsbypass.h
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
//
|
||||
// Created by maks on 05.06.2023.
|
||||
//
|
||||
|
||||
#ifndef POJAVLAUNCHER_NSBYPASS_H
|
||||
#define POJAVLAUNCHER_NSBYPASS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool linker_ns_load(const char* lib_search_path);
|
||||
void* linker_ns_dlopen(const char* name, int flag);
|
||||
void* linker_ns_dlopen_unique(const char* tmpdir, const char* name, int flag);
|
||||
struct android_namespace_t* ns_android_get_exported_namespace(const char*);
|
||||
|
||||
#endif //POJAVLAUNCHER_NSBYPASS_H
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GL/osmesa.h>
|
||||
#include "ctxbridges/osmesa_loader.h"
|
||||
#include "driver_helper/nsbypass.h"
|
||||
|
||||
#ifdef GLES_TEST
|
||||
#include <GLES2/gl2.h>
|
||||
@@ -21,6 +23,7 @@
|
||||
#include <android/rect.h>
|
||||
#include <string.h>
|
||||
#include <environ/environ.h>
|
||||
#include <android/dlext.h>
|
||||
#include "utils.h"
|
||||
#include "ctxbridges/gl_bridge.h"
|
||||
|
||||
@@ -46,8 +49,6 @@ struct PotatoBridge potatoBridge;
|
||||
|
||||
void* gbuffer;
|
||||
|
||||
void* egl_make_current(void* window);
|
||||
|
||||
void pojav_openGLOnLoad() {
|
||||
}
|
||||
void pojav_openGLOnUnload() {
|
||||
@@ -146,6 +147,79 @@ bool loadSymbols() {
|
||||
}
|
||||
}
|
||||
|
||||
//#define ADRENO_POSSIBLE
|
||||
#ifdef ADRENO_POSSIBLE
|
||||
//Checks if your graphics are Adreno. Returns true if your graphics are Adreno, false otherwise or if there was an error
|
||||
bool checkAdrenoGraphics() {
|
||||
EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if(eglDisplay == EGL_NO_DISPLAY || eglInitialize(eglDisplay, NULL, NULL) != EGL_TRUE) return false;
|
||||
EGLint egl_attributes[] = { EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE };
|
||||
EGLint num_configs = 0;
|
||||
if(eglChooseConfig(eglDisplay, egl_attributes, NULL, 0, &num_configs) != EGL_TRUE || num_configs == 0) {
|
||||
eglTerminate(eglDisplay);
|
||||
return false;
|
||||
}
|
||||
EGLConfig eglConfig;
|
||||
eglChooseConfig(eglDisplay, egl_attributes, &eglConfig, 1, &num_configs);
|
||||
const EGLint egl_context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
|
||||
EGLContext context = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, egl_context_attributes);
|
||||
if(context == EGL_NO_CONTEXT) {
|
||||
eglTerminate(eglDisplay);
|
||||
return false;
|
||||
}
|
||||
if(eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, context) != EGL_TRUE) {
|
||||
eglDestroyContext(eglDisplay, context);
|
||||
eglTerminate(eglDisplay);
|
||||
}
|
||||
const char* vendor = glGetString(GL_VENDOR);
|
||||
const char* renderer = glGetString(GL_RENDERER);
|
||||
bool is_adreno = false;
|
||||
if(strcmp(vendor, "Qualcomm") == 0 && strstr(renderer, "Adreno") != NULL) {
|
||||
is_adreno = true; // TODO: check for Turnip support
|
||||
}
|
||||
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(eglDisplay, context);
|
||||
eglTerminate(eglDisplay);
|
||||
return is_adreno;
|
||||
}
|
||||
void* load_turnip_vulkan() {
|
||||
if(!checkAdrenoGraphics()) return NULL;
|
||||
const char* native_dir = getenv("POJAV_NATIVEDIR");
|
||||
const char* cache_dir = getenv("TMPDIR");
|
||||
linker_ns_load(native_dir);
|
||||
void* linkerhook = linker_ns_dlopen("liblinkerhook.so", RTLD_LOCAL | RTLD_NOW);
|
||||
void* turnip_driver_handle = linker_ns_dlopen("libvulkan.adr.so", RTLD_LOCAL | RTLD_NOW);
|
||||
void (*linkerhook_set_data)(void*, void*, void*) = dlsym(linkerhook, "app__pojav_linkerhook_set_data");
|
||||
linkerhook_set_data(turnip_driver_handle, &android_dlopen_ext, &ns_android_get_exported_namespace);
|
||||
void* libvulkan = linker_ns_dlopen_unique(cache_dir, "libvulkan.so", RTLD_LOCAL | RTLD_NOW);
|
||||
return libvulkan;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void set_vulkan_ptr(void* ptr) {
|
||||
char envval[64];
|
||||
sprintf(envval, "%"PRIxPTR, (uintptr_t)ptr);
|
||||
setenv("VULKAN_PTR", envval, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
void load_vulkan() {
|
||||
if(getenv("POJAV_ZINK_PREFER_SYSTEM_DRIVER") == NULL) {
|
||||
#ifdef ADRENO_POSSIBLE
|
||||
void* result = load_turnip_vulkan();
|
||||
if(result != NULL) {
|
||||
printf("AdrenoSupp: Loaded Turnip, loader address: %p\n", result);
|
||||
set_vulkan_ptr(result);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
printf("OSMDroid: loading vulkan regularly...\n");
|
||||
void* vulkan_ptr = dlopen("libvulkan.so", RTLD_LAZY | RTLD_LOCAL);
|
||||
printf("OSMDroid: loaded vulkan, ptr=%p", vulkan_ptr);
|
||||
set_vulkan_ptr(vulkan_ptr);
|
||||
}
|
||||
|
||||
int pojavInit() {
|
||||
ANativeWindow_acquire(pojav_environ->pojavWindow);
|
||||
pojav_environ->savedWidth = ANativeWindow_getWidth(pojav_environ->pojavWindow);
|
||||
@@ -164,6 +238,7 @@ int pojavInit() {
|
||||
//loadSymbols();
|
||||
} else if (strcmp(renderer, "vulkan_zink") == 0) {
|
||||
pojav_environ->config_renderer = RENDERER_VK_ZINK;
|
||||
load_vulkan();
|
||||
setenv("GALLIUM_DRIVER","zink",1);
|
||||
loadSymbols();
|
||||
}
|
||||
@@ -221,20 +296,6 @@ void pojavSwapBuffers() {
|
||||
}
|
||||
}
|
||||
|
||||
void* egl_make_current(void* window) {
|
||||
EGLBoolean success = eglMakeCurrent_p(
|
||||
potatoBridge.eglDisplay,
|
||||
window==0 ? (EGLSurface *) 0 : potatoBridge.eglSurface,
|
||||
window==0 ? (EGLSurface *) 0 : potatoBridge.eglSurface,
|
||||
/* window==0 ? EGL_NO_CONTEXT : */ (EGLContext *) window
|
||||
);
|
||||
|
||||
if (success == EGL_FALSE) {
|
||||
printf("EGLBridge: Error: eglMakeCurrent() failed: %p\n", eglGetError_p());
|
||||
} else {
|
||||
printf("EGLBridge: eglMakeCurrent() succeed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool locked = false;
|
||||
void pojavMakeCurrent(void* window) {
|
||||
|
||||
BIN
app_pojavlauncher/src/main/jniLibs/arm64-v8a/libOSMesa.so
Executable file
BIN
app_pojavlauncher/src/main/jniLibs/arm64-v8a/libOSMesa.so
Executable file
Binary file not shown.
Binary file not shown.
BIN
app_pojavlauncher/src/main/jniLibs/arm64-v8a/libvulkan.adr.so
Normal file
BIN
app_pojavlauncher/src/main/jniLibs/arm64-v8a/libvulkan.adr.so
Normal file
Binary file not shown.
@@ -403,5 +403,6 @@
|
||||
<string name="preference_gyro_damper_window_title">Smoothing time</string>
|
||||
<string name="preference_gyro_damper_window_description">Reduce jitter in exchange of latency. 0 to disable it</string>
|
||||
|
||||
|
||||
<string name="preference_vulkan_driver_system_title">Use system Vulkan driver</string>
|
||||
<string name="preference_vulkan_driver_system_description">Force the launcher to use the system Vulkan driver instead of Turnip on Adreno GPUs. Only affects Zink.</string>
|
||||
</resources>
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
android:key="arc_capes"
|
||||
android:summary="@string/arc_capes_desc"
|
||||
android:title="@string/arc_capes_title" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="zinkPreferSystemDriver"
|
||||
android:summary="@string/preference_vulkan_driver_system_description"
|
||||
android:title="@string/preference_vulkan_driver_system_title"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user