From 9eb4b74a107712f197a4415629abeab065f9e2c2 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Tue, 26 Jan 2021 21:06:07 +0700 Subject: [PATCH] Try --- .../src/main/java/org/lwjgl/glfw/GLFW.java | 118 ++++++++---- Natives/CMakeLists.txt | 2 +- Natives/egl_bridge.c | 181 ++++++++++++++---- Natives/egl_bridge_ios.h | 9 - Natives/egl_bridge_ios.m | 83 -------- Natives/utils.h | 1 - 6 files changed, 232 insertions(+), 162 deletions(-) delete mode 100644 Natives/egl_bridge_ios.h delete mode 100644 Natives/egl_bridge_ios.m diff --git a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java index e566b093..a35b781a 100644 --- a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java +++ b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java @@ -24,6 +24,8 @@ import java.util.*; public class GLFW { + static FloatBuffer joystickData = (FloatBuffer)FloatBuffer.allocate(8).flip(); + static ByteBuffer buttonData = (ByteBuffer)ByteBuffer.allocate(8).flip(); /** The major version number of the GLFW library. This is incremented when the API is changed in non-compatible ways. */ public static final int GLFW_VERSION_MAJOR = 3; @@ -495,9 +497,10 @@ public class GLFW private static ArrayMap mGLFWWindowMap; public static boolean mGLFWIsGrabbing, mGLFWIsInputReady, mGLFWIsUseStackQueue = false; - public static final byte[] keyDownBuffer = new byte[316]; - + public static final byte[] keyDownBuffer = new byte[316]; + public static long mainContext = 0; static { + // Minecraft triggers a glfwPollEvents() on splash screen, so update window size there. CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_FRAMEBUFFER_SIZE, mGLFWWindowWidth, mGLFWWindowHeight, 0, 0); CallbackBridge.receiveCallback(CallbackBridge.EVENT_TYPE_WINDOW_SIZE, mGLFWWindowWidth, mGLFWWindowHeight, 0, 0); @@ -553,8 +556,10 @@ public class GLFW } private static native long nativeEglGetCurrentContext(); - // private static native boolean nativeEglInit(); + private static native boolean nativeEglInit(); public static native boolean nativeEglMakeCurrent(long window); + public static native void nativeEglDetachOnCurrentThread(); + public static native long nativeEglCreateContext(long contextSrc); private static native boolean nativeEglTerminate(); private static native boolean nativeEglSwapBuffers(); private static native boolean nativeEglSwapInterval(int inverval); @@ -751,10 +756,14 @@ public class GLFW public static GLFWWindowSizeCallback glfwSetWindowSizeCallback(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("GLFWwindowsizefun") GLFWWindowSizeCallbackI cbfun) { return mGLFWWindowSizeCallback = GLFWWindowSizeCallback.createSafe(nglfwSetWindowSizeCallback(window, memAddressSafe(cbfun))); } - + static boolean isGLFWReady; public static boolean glfwInit() { - mGLFWInitialTime = (double) System.nanoTime(); - return true; // nativeEglInit(); + if (!isGLFWReady) { + CallbackBridge.nativeAttachThreadToOther(false, false); + mGLFWInitialTime = (double) System.nanoTime(); + isGLFWReady = nativeEglInit(); + } + return isGLFWReady; } public static void glfwTerminate() { @@ -920,20 +929,10 @@ public class GLFW mGLFWGammaRamp = ramp; } - private static long mGLFWCurrentGLContextThread = -1; public static void glfwMakeContextCurrent(long window) { - long currentGLThreadId = Thread.currentThread().getId(); - // Long.parseLong(System.getProperty("glfwstub.internal.glthreadid", "-1")); - System.out.println("GLFW: glfwMakeContextCurrent() calling from thread ID " + currentGLThreadId + ", name: " + Thread.currentThread().getName()); - if (currentGLThreadId != -1 && currentGLThreadId != mGLFWCurrentGLContextThread) { - System.out.println("GLFW: Current context is set, creating shared context"); - if (!nativeEglMakeCurrent(window)) { - throw new RuntimeException("eglMakeCurrent() failed, check log file for more details"); - } - mGLFWCurrentGLContextThread = currentGLThreadId; - } else { - System.out.println("GLFW: glfwMakeContextCurrent() request is skipped"); - } + //Probably not the best idea to rely on program's internals to share the contexts... + // new Exception("Trace exception").printStackTrace(); + nativeEglMakeCurrent(window); } public static void glfwSwapBuffers(long window) { @@ -967,23 +966,23 @@ public class GLFW // GLFW Window functions public static long glfwCreateWindow(int width, int height, CharSequence title, long monitor, long share) { EventLoop.OffScreen.check(); + // Create an ACTUAL EGL context + long ptr = nativeEglCreateContext(share); + //nativeEglMakeCurrent(ptr); + GLFWWindowProperties win = new GLFWWindowProperties(); + // win.width = width; + // win.height = height; - // A good idea to fake pointer - long ptr = System.currentTimeMillis(); - - GLFWWindowProperties win = new GLFWWindowProperties(); - // win.width = width; - // win.height = height; - - win.width = mGLFWWindowWidth; - win.height = mGLFWWindowHeight; - - win.title = title; - - mGLFWWindowMap.put(ptr, win); + win.width = mGLFWWindowWidth; + win.height = mGLFWWindowHeight; + + win.title = title; + + mGLFWWindowMap.put(ptr, win); + mainContext = ptr; + return ptr; + //Return our context - // Prevent NULL check - return ptr; } public static void glfwDestroyWindow(long window) { @@ -1076,7 +1075,7 @@ public class GLFW break; case CallbackBridge.EVENT_TYPE_KEY: if (mGLFWKeyCallback != null) { - keyDownBuffer[dataArr[1]-32]=(byte)(int)dataArr[3]; + keyDownBuffer[dataArr[1]-32]=(byte)(int)dataArr[3]; mGLFWKeyCallback.invoke(ptr, dataArr[1], dataArr[2], dataArr[3], dataArr[4]); } break; @@ -1210,4 +1209,51 @@ public class GLFW public static String glfwGetClipboardString(@NativeType("GLFWwindow *") long window) { return CallbackBridge.nativeClipboard(CallbackBridge.CLIPBOARD_PASTE, null); } -} + + public static boolean glfwJoystickPresent(int jid) { + if(jid == 0) { + return true; + }else return false; + } + public static String glfwGetJoystickName(int jid) { + if(jid == 0) { + return "AIC event bus controller"; + }else return null; + } + public static FloatBuffer glfwGetJoystickAxes(int jid) { + if(jid == 0) { + return joystickData; + }else return null; + } + public static ByteBuffer glfwGetJoystickButtons(int jid) { + if(jid == 0) { + return buttonData; + }else return null; + } + public static ByteBuffer glfwGetjoystickHats(int jid) { + return null; + } + public static boolean glfwJoystickIsGamepad(int jid) { + if(jid == 0) return true; + else return false; + } + public static String glfwGetJoystickGUID(int jid) { + if(jid == 0) return "aio0"; + else return null; + } + public static long glfwGetJoystickUserPointer(int jid) { + return 0; + } + public static void glfwSetJoystickUserPointer(int jid, long pointer) { + + } + public static boolean glfwUpdateGamepadMappings(ByteBuffer string) { +return false; + } + public static String glfwGetGamepadName(int jid) { + return null; + } + public static boolean glfwGetGamepadState(int jid, GLFWGamepadState state) { + return false; + } +} \ No newline at end of file diff --git a/Natives/CMakeLists.txt b/Natives/CMakeLists.txt index eeceb367..6bb63c37 100644 --- a/Natives/CMakeLists.txt +++ b/Natives/CMakeLists.txt @@ -13,7 +13,7 @@ set_target_properties(PojavLauncher PROPERTIES MACOSX_FRAMEWORK_IDENTIFIER org.cmake.ExecutableTarget MACOSX_BUNDLE_INFO_PLIST "../Info.plist") -add_library(pojavexec SHARED log.m AppDelegate.m UILauncher.m ViewController.m egl_bridge_ios.m egl_bridge.c input_bridge_v3.c utils.c) +add_library(pojavexec SHARED log.m AppDelegate.m UILauncher.m ViewController.m egl_bridge.c input_bridge_v3.c utils.c) target_link_libraries(pojavexec "-Fresources/Frameworks" "-framework UIKit" diff --git a/Natives/egl_bridge.c b/Natives/egl_bridge.c index 6fa00993..d04d3313 100644 --- a/Natives/egl_bridge.c +++ b/Natives/egl_bridge.c @@ -8,7 +8,7 @@ #include #ifdef GLES_TEST -#include +#include "GLES2/gl2.h" #endif #include "egl_bridge_ios.h" @@ -16,6 +16,21 @@ #include "log.h" +struct PotatoBridge { + /* ANativeWindow */ void* androidWindow; + + /* EGLContext */ void* eglContextOld; + /* EGLContext */ void* eglContext; + /* EGLDisplay */ void* eglDisplay; + /* EGLSurface */ void* eglSurface; +/* + void* eglSurfaceRead; + void* eglSurfaceDraw; +*/ +}; +struct PotatoBridge potatoBridge; +EGLConfig config; + typedef void gl4esInitialize_func(); // typedef void gl4esSwapBuffers_func(); @@ -29,11 +44,6 @@ void pojav_openGLOnUnload() { } -void terminateEgl() { - debug("ES2Bridge: Terminating\n"); - // clearCurrentContext(CURR_GL_CONTEXT); -} - JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setenv(JNIEnv *env, jclass clazz, jstring name, jstring value, jboolean overwrite) { char const *name_c = (*env)->GetStringUTFChars(env, name, NULL); char const *value_c = (*env)->GetStringUTFChars(env, value, NULL); @@ -45,32 +55,128 @@ JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setenv(JNIEnv *en } JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_saveGLContext(JNIEnv* env, jclass clazz) { - CURR_GL_CONTEXT = getCurrentContext(); - if (CURR_GL_CONTEXT == NULL) { - debug("OpenGLES context is NULL..."); - assert(CURR_GL_CONTEXT != NULL); - } +} + +void terminateEgl() { + printf("EGLBridge: Terminating\n"); + eglMakeCurrent(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(potatoBridge.eglDisplay, potatoBridge.eglSurface); + eglDestroyContext(potatoBridge.eglDisplay, potatoBridge.eglContext); + eglTerminate(potatoBridge.eglDisplay); + eglReleaseThread(); - // Clear current GL context to later set on another thread - // clearCurrentContext(); + potatoBridge.eglContext = EGL_NO_CONTEXT; + potatoBridge.eglDisplay = EGL_NO_DISPLAY; + potatoBridge.eglSurface = EGL_NO_SURFACE; +} + +JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setupBridgeWindow(JNIEnv* env, jclass clazz, jobject surface) { + potatoBridge.androidWindow = ANativeWindow_fromSurface(env, surface); } JNIEXPORT jlong JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglGetCurrentContext(JNIEnv* env, jclass clazz) { - return (jlong) (uintptr_t) CURR_GL_CONTEXT; + return eglGetCurrentContext(); } -/* +static const EGLint ctx_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE +}; JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglInit(JNIEnv* env, jclass clazz) { + if (potatoBridge.eglDisplay == NULL || potatoBridge.eglDisplay == EGL_NO_DISPLAY) { + potatoBridge.eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (potatoBridge.eglDisplay == EGL_NO_DISPLAY) { + printf("EGLBridge: Error eglGetDefaultDisplay() failed: %p\n", eglGetError()); + return JNI_FALSE; + } + } + + printf("EGLBridge: Initializing\n"); + // printf("EGLBridge: ANativeWindow pointer = %p\n", potatoBridge.androidWindow); + //(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); + if (!eglInitialize(potatoBridge.eglDisplay, NULL, NULL)) { + printf("EGLBridge: Error eglInitialize() failed\n"); + return JNI_FALSE; + } + + static const EGLint attribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + // Minecraft required on initial 24 + EGL_DEPTH_SIZE, 16, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + EGLint num_configs; + EGLint vid; + + if (!eglChooseConfig(potatoBridge.eglDisplay, attribs, &config, 1, &num_configs)) { + printf("EGLBridge: Error couldn't get an EGL visual config\n"); + return JNI_FALSE; + } + + assert(config); + assert(num_configs > 0); + + if (!eglGetConfigAttrib(potatoBridge.eglDisplay, config, EGL_NATIVE_VISUAL_ID, &vid)) { + printf("EGLBridge: Error eglGetConfigAttrib() failed\n"); + return JNI_FALSE; + } + + ANativeWindow_setBuffersGeometry(potatoBridge.androidWindow, 0, 0, vid); + + eglBindAPI(EGL_OPENGL_ES_API); + + potatoBridge.eglSurface = eglCreateWindowSurface(potatoBridge.eglDisplay, config, potatoBridge.androidWindow, NULL); + + if (!potatoBridge.eglSurface) { + printf("EGLBridge: Error eglCreateWindowSurface failed: %p\n", eglGetError()); + //(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); + return JNI_FALSE; + } + + // sanity checks + { + EGLint val; + assert(eglGetConfigAttrib(potatoBridge.eglDisplay, config, EGL_SURFACE_TYPE, &val)); + assert(val & EGL_WINDOW_BIT); + } + + + printf("EGLBridge: Initialized!\n"); + printf("EGLBridge: ThreadID=%d\n", gettid()); + printf("EGLBridge: EGLDisplay=%p, EGLSurface=%p\n", +/* window==0 ? EGL_NO_CONTEXT : */ + potatoBridge.eglDisplay, + potatoBridge.eglSurface + ); return JNI_TRUE; } -*/ + JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglMakeCurrent(JNIEnv* env, jclass clazz, jlong window) { - debug("ES2Bridge: making current\n"); - - jboolean ret = makeCurrentContext(CURR_GL_CONTEXT); - if (!ret) { - return ret; + + if (window != 0x1) { + printf("Making current on window %p\n", window); + EGLBoolean success = eglMakeCurrent( + potatoBridge.eglDisplay, + potatoBridge.eglSurface, + potatoBridge.eglSurface, + /* window==0 ? EGL_NO_CONTEXT : */ (EGLContext *) window + ); + if (success == EGL_FALSE) { + printf("Error: eglMakeCurrent() failed: %p\n", eglGetError()); } + // Test +#ifdef GLES_TEST + glClearColor(0.4f, 0.4f, 0.4f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(potatoBridge.eglDisplay, potatoBridge.eglSurface); + printf("First frame error: %p\n", eglGetError()); +#endif + GL4ES_HANDLE = dlopen("libGL.dylib", RTLD_GLOBAL); debug("libGL = %p", GL4ES_HANDLE); @@ -85,8 +191,20 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglMakeCurrent(JNIEnv* return ret; } +JNIEXPORT void JNICALL +Java_org_lwjgl_glfw_GLFW_nativeEglDetachOnCurrentThread(JNIEnv *env, jclass clazz) { + //Obstruct the context on the current thread + eglMakeCurrent(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} +JNIEXPORT jlong JNICALL +Java_org_lwjgl_glfw_GLFW_nativeEglCreateContext(JNIEnv *env, jclass clazz, jlong contextSrc) { + EGLContext* ctx = eglCreateContext(potatoBridge.eglDisplay,config,(void*)contextSrc,ctx_attribs); + printf("Created CTX pointer = %p\n",ctx); + //(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); + return (long)ctx; +} JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglTerminate(JNIEnv* env, jclass clazz) { - clearCurrentContext(); + terminateEgl(); return JNI_TRUE; } @@ -96,17 +214,16 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglSwapBuffers(JNIEnv return JNI_FALSE; } - // gl4esSwapBuffers(); - flushBuffer(); - return JNI_TRUE; + jboolean result = (jboolean) eglSwapBuffers(potatoBridge.eglDisplay, potatoBridge.eglSurface); + if (!result) { + if (eglGetError() == EGL_BAD_SURFACE) { + stopMakeCurrent = true; + closeGLFWWindow(); + } + } + return result; } JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglSwapInterval(JNIEnv *env, jclass clazz, jint interval) { - // return eglSwapInterval(potatoBridge.eglDisplay, interval); - // setSwapInterval(CURR_GL_CONTEXT. interval); - - debug("FIXME: swap interval at runtime is not supported on iOS!"); - - return JNI_FALSE; + return eglSwapInterval(potatoBridge.eglDisplay, interval); } - diff --git a/Natives/egl_bridge_ios.h b/Natives/egl_bridge_ios.h deleted file mode 100644 index 438d8b7b..00000000 --- a/Natives/egl_bridge_ios.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#include "jni.h" - -void *createContext(); -void *getCurrentContext(); -jboolean makeCurrentContext(void *context); -jboolean clearCurrentContext(); -void flushBuffer(); diff --git a/Natives/egl_bridge_ios.m b/Natives/egl_bridge_ios.m deleted file mode 100644 index a4ff7a20..00000000 --- a/Natives/egl_bridge_ios.m +++ /dev/null @@ -1,83 +0,0 @@ -// Based on https://github.com/jschwartzenberg/openjfx8/blob/master/modules/graphics/src/main/native-prism-es2/ios/IOSWindowSystemInterface.m - -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#import -#import "MGLKit.h" -#import - -#import "AppDelegate.h" -#import "egl_bridge_ios.h" - -#include "EGL/egl.h" -#include "GLES2/gl2.h" -#include "GLES2/gl2ext.h" - -#if defined (_LP64) -# define jlong_to_ptr(a) ((void*)(a)) -# define ptr_to_jlong(a) ((jlong)(a)) -#else -# define jlong_to_ptr(a) ((void*)(int)(a)) -# define ptr_to_jlong(a) ((jlong)(int)(a)) -#endif - -void *createContext() { - MGLContext *ctx = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES2]; - return ptr_to_jlong(ctx); -} - -void *getCurrentContext() { - MGLContext *ctx = [MGLContext currentContext]; - return ptr_to_jlong(ctx); -} - -jboolean makeCurrentContext(void *context) { - if ([MGLContext setCurrentContext:(__bridge MGLContext *)jlong_to_ptr(context)] == YES) { - // glViewport(0, 0, width_c, height_c); - return JNI_TRUE; - } - - return JNI_FALSE; -} - -jboolean clearCurrentContext() { - if ([MGLContext setCurrentContext:nil] == YES) { - return JNI_TRUE; - } - - return JNI_FALSE; -} - -void flushBuffer() { - // glBindRenderbuffer(GL_RENDERBUFFER, RenderBuffer); - - // [[MGLContext currentContext] presentRenderbuffer:GL_RENDERBUFFER]; - - eglSwapBuffers(); - - // prepare new buffer - // glBindFramebuffer(GL_FRAMEBUFFER, FrameBuffer); -} diff --git a/Natives/utils.h b/Natives/utils.h index c2a7536c..521923d0 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -8,7 +8,6 @@ #define ACTION_UP 1 #define ACTION_MOVE 2 -void* CURR_GL_CONTEXT; void* GL4ES_HANDLE; JavaVM* runtimeJavaVMPtr;