From e079e86a8034d221f0686cbefaa114d9c83fc1e0 Mon Sep 17 00:00:00 2001 From: Duy Tran Khanh Date: Thu, 5 Aug 2021 15:17:56 +0700 Subject: [PATCH] Changes - Automatically set overrideWidth and overrideHeight - Multi-context moment. Current status of Forge 1.12.2: Exception type: EXC_BAD_ACCESS (SIGSEGV) Exception subtype: KERN_INVALID_ADDRESS: 0x964 Exception codes: 0x0000000000000001, 0x0000000000000964 Culprit: Unknown VM Protection: 0x964 is not in any region. Triggered by thread: 20 Thread name: Call stack: 0 libgl4es_115.dylib 0x000000012196738c 0x121900000 + 422796 // realize_glenv 1 libgl4es_115.dylib 0x00000001219672dc 0x121900000 + 422620 // realize_glenv 2 libgl4es_115.dylib 0x0000000121966e78 0x121900000 + 421496 // fpe_glDrawArrays 3 libgl4es_115.dylib 0x000000012199d4e4 0x121900000 + 644324 // draw_renderlist 4 libgl4es_115.dylib 0x000000012197e39c 0x121900000 + 517020 // gl4es_flush 5 libgl4es_115.dylib 0x00000001219609e4 0x121900000 + 395748 // proxy_glEnable --- .../java/net/kdt/pojavlaunch/uikit/UIKit.java | 4 + .../main/java/org/lwjgl/opengl/ContextGL.java | 22 +- .../main/java/org/lwjgl/opengl/Display.java | 48 ++-- .../main/java/org/lwjgl/opengl/GLContext.java | 11 +- Natives/SurfaceViewController.m | 9 +- Natives/egl_bridge.m | 210 +++++------------- Natives/utils.h | 3 + 7 files changed, 120 insertions(+), 187 deletions(-) diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java index 441c031e..679bc629 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/uikit/UIKit.java @@ -73,6 +73,10 @@ public class UIKit { } public static void callback_SurfaceViewController_launchMinecraft(int width, int height) { + MCOptionUtils.load(); + MCOptionUtils.set("overrideWidth", Integer.toString(width)); + MCOptionUtils.set("overrideHeight", Integer.toString(height)); + MCOptionUtils.save(); System.setProperty("cacio.managed.screensize", width + "x" + height); GLFW.internalChangeMonitorSize(width, height); diff --git a/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java b/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java index 9df0f960..589af3c0 100644 --- a/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java +++ b/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java @@ -63,7 +63,8 @@ final class ContextGL implements Context { private static final ThreadLocal current_context_local = new ThreadLocal(); /** Handle to the native GL rendering context */ - private final ByteBuffer handle; + //private final ByteBuffer handle; + private final long handle; private final PeerInfo peer_info; private final ContextAttribs contextAttribs; @@ -96,6 +97,14 @@ final class ContextGL implements Context { return current_context_local.get(); } + ContextGL(long handle) { + this.peer_info = null; + this.contextAttribs = null; + this.forwardCompatible = false; + this.handle = handle; + System.out.println("LWJGLX: ready-handle context created"); + } + /** Create a context with the specified peer info and shared context */ ContextGL(PeerInfo peer_info, ContextAttribs attribs, ContextGL shared_context) throws LWJGLException { ContextGL context_lock = shared_context != null ? shared_context : this; @@ -121,7 +130,11 @@ final class ContextGL implements Context { forwardCompatible = false; - this.handle = null; + long share = 0; + if(shared_context != null) { + share = shared_context.handle; + } + this.handle = GLFW.nativeEglCreateContext(share); // implementation.create(peer_info, attribList, shared_context != null ? shared_context.handle : null); /* } catch (LWJGLException e) { // GLContext.unloadOpenGLLibrary(); @@ -184,12 +197,13 @@ final class ContextGL implements Context { throw new IllegalStateException("Context is destroyed"); thread = Thread.currentThread(); current_context_local.set(this); - GLFW.glfwMakeContextCurrent(Display.Window.handle); + GLFW.glfwMakeContextCurrent(handle); + GLContext.initCapabilities(); isCurrent = true; } ByteBuffer getHandle() { - return handle; + return null; // handle } /** Query whether the context is current */ diff --git a/JavaApp/src/main/java/org/lwjgl/opengl/Display.java b/JavaApp/src/main/java/org/lwjgl/opengl/Display.java index 91f2a99c..4fd85518 100644 --- a/JavaApp/src/main/java/org/lwjgl/opengl/Display.java +++ b/JavaApp/src/main/java/org/lwjgl/opengl/Display.java @@ -61,7 +61,7 @@ public class Display { private static boolean window_created; /** The Drawable instance that tracks the current Display context */ - private static DrawableLWJGL drawable; + private static volatile DrawableLWJGL drawable = null; private static Canvas parent; @@ -206,30 +206,13 @@ public class Display { // System.out.println("TODO: Implement Display.create(PixelFormat, // Drawable)"); // TODO create(pixel_format); - - final DrawableGL drawable = new DrawableGL() { - public void destroy() { - synchronized ( GlobalLock.lock ) { - if ( !isCreated() ) - return; - - releaseDrawable(); - super.destroy(); - destroyWindow(); - // x = y = -1; - // cached_icons = null; - reset(); - } - } - }; - Display.drawable = drawable; try { drawable.setPixelFormat(pixel_format, null); try { createWindow(); try { - drawable.context = new ContextGL(drawable.peer_info, null /* attribs */, shared_drawable != null ? ((DrawableGL)shared_drawable).getContext() : null); + ((DrawableGL) drawable).context = new ContextGL(((DrawableGL) drawable).peer_info, null /* attribs */, shared_drawable != null ? ((DrawableGL)shared_drawable).getContext() : null); try { makeCurrentAndSetSwapInterval(); initContext(); @@ -311,8 +294,8 @@ public class Display { Window.charCallback = new GLFWCharCallback() { @Override public void invoke(long window, int codepoint) { - GLFWInputImplementation.singleton.putKeyboardEvent(KeyCodes.toLwjglKey(32),(byte)1,(int)codepoint,Sys.getNanoTime(),false); - GLFWInputImplementation.singleton.putKeyboardEvent(KeyCodes.toLwjglKey(32),(byte)0,(int)codepoint,Sys.getNanoTime(),false); + GLFWInputImplementation.singleton.putKeyboardEvent(0,(byte)1,(int)codepoint,Sys.getNanoTime(),false); + //GLFWInputImplementation.singleton.putKeyboardEvent(0,(byte)0,(int)codepoint,Sys.getNanoTime(),false); } }; @@ -413,7 +396,25 @@ public class Display { displayY = (monitorHeight - mode.getHeight()) / 2; } - glfwMakeContextCurrent(Window.handle); + //glfwMakeContextCurrent(Window.handle); + final DrawableGL drawable = new DrawableGL() { + public void destroy() { + synchronized ( GlobalLock.lock ) { + if ( !isCreated() ) + return; + + releaseDrawable(); + super.destroy(); + destroyWindow(); + // x = y = -1; + // cached_icons = null; + reset(); + } + } + }; + drawable.context = new ContextGL(Window.handle); + drawable.context.makeCurrent(); + Display.drawable = drawable; context = org.lwjgl.opengl.GLContext.createFromCurrent(); glfwSwapInterval(0); @@ -732,6 +733,7 @@ public class Display { } }; + displayCreated = true; } @@ -918,6 +920,8 @@ public class Display { windowTitle = title; } + public static String getTitle() { return windowTitle; } + public static boolean isCloseRequested() { return glfwWindowShouldClose(Window.handle) == true; } diff --git a/JavaApp/src/main/java/org/lwjgl/opengl/GLContext.java b/JavaApp/src/main/java/org/lwjgl/opengl/GLContext.java index d68aac1e..913a8383 100644 --- a/JavaApp/src/main/java/org/lwjgl/opengl/GLContext.java +++ b/JavaApp/src/main/java/org/lwjgl/opengl/GLContext.java @@ -3,13 +3,18 @@ package org.lwjgl.opengl; public class GLContext { - private static ContextCapabilities contextCapabilities = new ContextCapabilities(); + private static ThreadLocal contextCapabilities = new ThreadLocal<>(); public static GLContext createFromCurrent() { return new GLContext(); } - + public static void initCapabilities() { + if(contextCapabilities.get() == null) { + System.out.println("LWJGLX: GL caps init"); + contextCapabilities.set(new ContextCapabilities()); + } + } public static ContextCapabilities getCapabilities() { - return contextCapabilities; + return contextCapabilities.get(); } } diff --git a/Natives/SurfaceViewController.m b/Natives/SurfaceViewController.m index d974bfd1..ffff618d 100644 --- a/Natives/SurfaceViewController.m +++ b/Natives/SurfaceViewController.m @@ -199,16 +199,13 @@ int notchOffset; // [self setPreferredFramesPerSecond:1000]; // Init GLES - self.context = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES3]; - - if (!self.context) { - self.context = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES2]; - } + sharegroup = [[MGLSharegroup alloc] init]; + self.context = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES3 sharegroup:sharegroup]; if (!self.context) { NSLog(@"Failed to create ES context"); } - + surfaceView.context = self.context; #ifndef USE_EGL glContext = self.context; diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index 622ea84c..4a88201d 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -26,8 +27,9 @@ struct PotatoBridge { void* eglSurfaceDraw; */ }; -struct PotatoBridge potatoBridge; EGLConfig config; +mach_port_t mainThreadID; +struct PotatoBridge potatoBridge; typedef void gl4esInitialize_func(); // typedef void gl4esSwapBuffers_func(); @@ -62,18 +64,8 @@ JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_saveGLContext(JNI void terminateEgl() { debug("EGLBridge: Terminating"); -#ifdef USE_EGL - eglMakeCurrent(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -#else [MGLContext setCurrentContext:nil]; -#endif -/* - eglDestroySurface(potatoBridge.eglDisplay, potatoBridge.eglSurface); - eglDestroyContext(potatoBridge.eglDisplay, potatoBridge.eglContext); - eglTerminate(potatoBridge.eglDisplay); - eglReleaseThread(); -*/ potatoBridge.eglContext = EGL_NO_CONTEXT; potatoBridge.eglDisplay = EGL_NO_DISPLAY; potatoBridge.eglSurface = EGL_NO_SURFACE; @@ -83,170 +75,83 @@ JNIEXPORT jlong JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglGetCurrentContext(JNIE return (jlong) eglGetCurrentContext(); } -static const EGLint ctx_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE -}; JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglInit(JNIEnv* env, jclass clazz) { isInputReady = 1; - -/* - 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; - } - - 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); - } -*/ + mainThreadID = pthread_mach_thread_np(pthread_self()); debug("EGLBridge: Initialized!"); // printf("EGLBridge: ThreadID=%d\n", gettid()); debug("EGLBridge: EGLDisplay=%p, EGLSurface=%p", /* window==0 ? EGL_NO_CONTEXT : */ - potatoBridge.eglDisplay, - potatoBridge.eglSurface + potatoBridge.eglDisplay, + potatoBridge.eglSurface ); return JNI_TRUE; } JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglMakeCurrent(JNIEnv* env, jclass clazz, jlong window) { - if (window != 0x1) { - debug("Making current on window %llx", window); - EGLBoolean success; -#ifdef USE_EGL - success = eglMakeCurrent( - potatoBridge.eglDisplay, - potatoBridge.eglSurface, - potatoBridge.eglSurface, - (EGLContext *) window - ); -#else - [MGLContext setCurrentContext:nil]; - success = [MGLContext setCurrentContext:glContext] == YES; -#endif + mach_port_t tid = pthread_mach_thread_np(pthread_self()); + MGLContext *currCtx = MGLContext.currentContext; + MGLContext *localContext = [[NSThread currentThread] threadDictionary][@"gl_context"]; + EGLBoolean success; - if (success == EGL_FALSE) { - debug("Error: eglMakeCurrent() failed: %x", eglGetError()); + debug("EGLBridge: Comparing: thr=%d, this=%p, curr=%p", (int)tid, (void *)window, currCtx); + debug("EGLBridge: Making current on window %p on thread (%d)", (void *)window, (int)tid); + [MGLContext setCurrentContext:nil]; + if (window != 0) { + if ((jlong)localContext != window) { + debug("EGLBridge ERROR: Context mismatch! local=%p, input=%p", localContext, (void *)window); } - - debug("EGLBridge: Trigger an initial swapBuffers"); - [viewController resume]; - - // Test -#ifdef GLES_TEST - glClearColor(0.4f, 0.4f, 0.4f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(potatoBridge.eglDisplay, potatoBridge.eglSurface); - debug("First frame error: %x", eglGetError()); -#endif - if (success == EGL_TRUE) { - GL4ES_HANDLE = dlopen(getenv("GL4ES_LIBNAME"), RTLD_GLOBAL); - debug("libGL=%p", GL4ES_HANDLE); - - gl4esInitialize_func *gl4esInitialize = (gl4esInitialize_func*) dlsym(GL4ES_HANDLE, "initialize_gl4es"); - // debug("initialize_gl4es = %p", gl4esInitialize); - - // gl4esSwapBuffers = (gl4esSwapBuffers_func*) dlsym(GL4ES_HANDLE, "gl4es_SwapBuffers_currentContext"); - - gl4esInitialize(); - debug("GL4ES init success"); - } - - // idk this should convert or just `return success;`... - return success == EGL_TRUE ? JNI_TRUE : JNI_FALSE; - } else { - (*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); - return JNI_FALSE; + success = [MGLContext setCurrentContext:localContext] == YES; } + + if (success == EGL_FALSE) { + debug("Error: eglMakeCurrent() failed: %x", eglGetError()); + } + + debug("EGLBridge: Trigger an initial swapBuffers"); + [viewController resume]; + + // Test +#ifdef GLES_TEST + glClearColor(0.4f, 0.4f, 0.4f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(potatoBridge.eglDisplay, potatoBridge.eglSurface); + debug("First frame error: %x", eglGetError()); +#endif + if (success == EGL_TRUE && GL4ES_HANDLE == NULL) { + GL4ES_HANDLE = dlopen(getenv("GL4ES_LIBNAME"), RTLD_GLOBAL); + debug("libGL=%p", GL4ES_HANDLE); + + gl4esInitialize_func *gl4esInitialize = (gl4esInitialize_func*) dlsym(GL4ES_HANDLE, "initialize_gl4es"); + // debug("initialize_gl4es = %p", gl4esInitialize); + + // gl4esSwapBuffers = (gl4esSwapBuffers_func*) dlsym(GL4ES_HANDLE, "gl4es_SwapBuffers_currentContext"); + + gl4esInitialize(); + debug("GL4ES init success"); + } + + // idk this should convert or just `return success;`... + return success == EGL_TRUE ? JNI_TRUE : JNI_FALSE; } JNIEXPORT void JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglDetachOnCurrentThread(JNIEnv *env, jclass clazz) { -#ifdef USE_EGL - eglMakeCurrent(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -#else [MGLContext setCurrentContext:nil]; -#endif } JNIEXPORT jlong JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglCreateContext(JNIEnv *env, jclass clazz, jlong contextSrc) { - void* ctx; - if (contextSrc == 0) { -#ifdef USE_EGL - EGLint numConfigs; - EGLBoolean result; - result = eglGetConfigs(potatoBridge.eglDisplay, NULL, 0, &numConfigs); - assert(result != EGL_FALSE); - EGLConfig configs[numConfigs]; - result = eglGetConfigs(potatoBridge.eglDisplay, configs, numConfigs, &numConfigs); - assert(result != EGL_FALSE ); - config = configs[0]; - - ctx = (void*) eglCreateContext(potatoBridge.eglDisplay, config, (void*)potatoBridge.eglContext, ctx_attribs); - - debug("Created CTX pointer=%p, shareCtx=%x, error=%x", ctx, potatoBridge.eglContext, eglGetError()); -#else - ctx = (void*) potatoBridge.eglContext; - debug("Using CTX pointer=%p, shareCtx=NULL", ctx); -#endif + MGLContext *localContext; + mach_port_t tid = pthread_mach_thread_np(pthread_self()); + if (tid != mainThreadID) { + localContext = [[MGLContext alloc] initWithAPI:kMGLRenderingAPIOpenGLES3 sharegroup:sharegroup]; + debug("EGLBridge: Created CTX pointer=%p, shareCTX=%p, thread=%d", localContext, (void *)contextSrc, (int)tid); } else { - ctx = (void*) eglCreateContext(potatoBridge.eglDisplay,config,(void*)contextSrc,ctx_attribs); - debug("Created CTX pointer=%p, shareCtx=%p, error=%x", ctx, (void*)contextSrc, eglGetError()); + localContext = viewController.glView.context; } - //(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); - return (long)ctx; + [[NSThread currentThread] threadDictionary][@"gl_context"] = localContext; + debug("EGLBridge: Created CTX pointer=%p, shareCTX=%p, thread=%d", localContext, (void *)contextSrc, (int)tid); + return (jlong)localContext; } JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglTerminate(JNIEnv* env, jclass clazz) { @@ -264,8 +169,9 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglSwapBuffers(JNIEnv jboolean result = (jboolean) eglSwapBuffers(potatoBridge.eglDisplay, eglGetCurrentSurface(EGL_DRAW)); if (!result) { + mach_port_t tid = pthread_mach_thread_np(pthread_self()); EGLint error = eglGetError(); - debug("eglSwapBuffers error: %x", error); + debug("eglSwapBuffers error=%x, thread=%d isMainThread=%d", error, (int)tid, mainThreadID == tid); if (error == EGL_BAD_SURFACE) { stopMakeCurrent = true; closeGLFWWindow(); diff --git a/Natives/utils.h b/Natives/utils.h index ad1bd64e..d1d08f95 100644 --- a/Natives/utils.h +++ b/Natives/utils.h @@ -1,5 +1,6 @@ #pragma once +#import "MGLKit.h" #include #include "jni.h" @@ -31,6 +32,8 @@ #define SPECIALBTN_SCROLLUP -7 #define SPECIALBTN_SCROLLDOWN -8 +MGLSharegroup* sharegroup; + void* GL4ES_HANDLE; JavaVM* runtimeJavaVMPtr;