diff --git a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java index 56917714..d57e18ea 100644 --- a/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java +++ b/JavaApp/src/main/java/org/lwjgl/glfw/GLFW.java @@ -535,19 +535,10 @@ public class GLFW } } } catch (IllegalAccessException e) { - // This will never happend since this is accessing itself + // This will never happen since this is accessing itself } } - private static native long nativeEglGetCurrentContext(); - 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); - private static native long nglfwSetCharCallback(long window, long ptr); private static native long nglfwSetCharModsCallback(long window, long ptr); private static native long nglfwSetCursorEnterCallback(long window, long ptr); @@ -577,34 +568,25 @@ public class GLFW throw new UnsupportedOperationException(); } - private static final SharedLibrary GLFW = new SharedLibrary() { - @java.lang.Override - public String getName() { - return "GLFW"; - } + private static final SharedLibrary GLFW = Library.loadNative(GLFW.class, "org.lwjgl.glfw", System.getenv("BUNDLE_PATH") + "/PojavLauncher", true); - @Nullable - @java.lang.Override - public String getPath() { - return null; - } - @java.lang.Override - public long getFunctionAddress(ByteBuffer functionName) { - return 1; - } + /** Contains the function pointers loaded from the glfw {@link SharedLibrary}. */ + public static final class Functions { - @java.lang.Override - public void free() { + private Functions() {} - } - - @java.lang.Override - public long address() { - return 1; - } - }; - // Library.loadNative(GLFW.class, "org.lwjgl.glfw", Configuration.GLFW_LIBRARY_NAME.get(Platform.mapLibraryNameBundled("glfw")), true); + /** Function address. */ + public static final long + Init = apiGetFunctionAddress(GLFW, "pojavInit"), + CreateContext = apiGetFunctionAddress(GLFW, "pojavCreateContext"), + GetCurrentContext = apiGetFunctionAddress(GLFW, "pojavGetCurrentContext"), + //DetachOnCurrentThread = apiGetFunctionAddress(GLFW, "pojavDetachOnCurrentThread"), + MakeContextCurrent = apiGetFunctionAddress(GLFW, "pojavMakeCurrent"), + Terminate = apiGetFunctionAddress(GLFW, "pojavTerminate"), + SwapBuffers = apiGetFunctionAddress(GLFW, "pojavSwapBuffers"), + SwapInterval = apiGetFunctionAddress(GLFW, "pojavSwapInterval"); + } public static SharedLibrary getLibrary() { return GLFW; @@ -804,12 +786,13 @@ public class GLFW return lastCallback; } + static boolean isGLFWReady; - public static boolean glfwInit() { - if (!isGLFWReady) { - // CallbackBridge.nativeAttachThreadToOther(false, false); - mGLFWInitialTime = (double) System.nanoTime(); - isGLFWReady = nativeEglInit(); + public static boolean glfwInit() { + if (!isGLFWReady) { + mGLFWInitialTime = (double) System.nanoTime(); + long __functionAddress = Functions.Init; + isGLFWReady = invokeI(__functionAddress) != 0; } return isGLFWReady; } @@ -818,15 +801,17 @@ public class GLFW mGLFWIsInputReady = false; CallbackBridge.nativeSetInputReady(false); - nativeEglTerminate(); - } + long __functionAddress = Functions.Terminate; + invokeV(__functionAddress); + } - public static void glfwInitHint(int hint, int value) { } + public static void glfwInitHint(int hint, int value) { } - @NativeType("GLFWwindow *") - public static long glfwGetCurrentContext() { - return nativeEglGetCurrentContext(); - } + @NativeType("GLFWwindow *") + public static long glfwGetCurrentContext() { + long __functionAddress = Functions.GetCurrentContext; + return invokeP(__functionAddress); + } public static void glfwGetFramebufferSize(@NativeType("GLFWwindow *") long window, @Nullable @NativeType("int *") IntBuffer width, @Nullable @NativeType("int *") IntBuffer height) { if (CHECKS) { @@ -979,20 +964,21 @@ public class GLFW mGLFWGammaRamp = ramp; } - public static void glfwMakeContextCurrent(long window) { - //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) { - nativeEglSwapBuffers(); - } - - public static void glfwSwapInterval(int interval) { - nativeEglSwapInterval(interval); + public static void glfwMakeContextCurrent(@NativeType("GLFWwindow *") long window) { + long __functionAddress = Functions.MakeContextCurrent; + invokePV(window, __functionAddress); } - + + public static void glfwSwapBuffers(@NativeType("GLFWwindow *") long window) { + long __functionAddress = Functions.SwapBuffers; + invokePV(window, __functionAddress); + } + + public static void glfwSwapInterval(int interval) { + long __functionAddress = Functions.SwapInterval; + invokeV(interval, __functionAddress); + } + // private static double mTime = 0d; public static double glfwGetTime() { // Boardwalk: just use system timer @@ -1013,28 +999,27 @@ public class GLFW return 60; } - // GLFW Window functions + // GLFW Window functions + public static long nglfwCreateContext(long share) { + return invokePP(share, Functions.CreateContext); + } 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); + // Create an ACTUAL EGL context + long ptr = nglfwCreateContext(share); //nativeEglMakeCurrent(ptr); - GLFWWindowProperties win = new GLFWWindowProperties(); + GLFWWindowProperties win = new GLFWWindowProperties(); - win.width = width; - win.height = height; + win.width = width; + win.height = height; - // win.width = mGLFWWindowWidth; - // win.height = mGLFWWindowHeight; - - win.title = title; + win.title = title; - mGLFWWindowMap.put(ptr, win); - mainContext = ptr; - return ptr; + mGLFWWindowMap.put(ptr, win); + mainContext = ptr; + return ptr; //Return our context - - } + } public static void glfwDestroyWindow(long window) { // Check window exists @@ -1047,8 +1032,8 @@ public class GLFW public static void glfwGetWindowSize(long window, IntBuffer width, IntBuffer height) { if (width != null) width.put(internalGetWindow(window).width); - if (height != null) height.put(internalGetWindow(window).height); - } + if (height != null) height.put(internalGetWindow(window).height); + } public static void glfwSetWindowPos(long window, int x, int y) { internalGetWindow(window).x = x; diff --git a/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java b/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java index 589af3c0..b4b3c0a1 100644 --- a/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java +++ b/JavaApp/src/main/java/org/lwjgl/opengl/ContextGL.java @@ -134,7 +134,7 @@ final class ContextGL implements Context { if(shared_context != null) { share = shared_context.handle; } - this.handle = GLFW.nativeEglCreateContext(share); + this.handle = GLFW.nglfwCreateContext(share); // implementation.create(peer_info, attribList, shared_context != null ? shared_context.handle : null); /* } catch (LWJGLException e) { // GLContext.unloadOpenGLLibrary(); diff --git a/JavaApp/src/main/java/org/lwjgl/opengl/GL.java b/JavaApp/src/main/java/org/lwjgl/opengl/GL.java index a289de6e..bbcf4d1b 100644 --- a/JavaApp/src/main/java/org/lwjgl/opengl/GL.java +++ b/JavaApp/src/main/java/org/lwjgl/opengl/GL.java @@ -90,7 +90,7 @@ public final class GL { create(); } } - + private static native void nativeRegalMakeCurrent(); private GL() {} @@ -368,15 +368,15 @@ public final class GL { GLCapabilities caps = null; try { - if (System.getenv("RENDERER").startsWith("libgl4es") || isUsingRegal) { + if (System.getenv("POJAV_RENDERER").equals("opengles3_virgl") || System.getenv("POJAV_RENDERER").equals("vulkan_zink")) { + int[] dims = getNativeWidthHeight(); + callJPI(GLFW.glfwGetCurrentContext(),getGraphicsBufferAddr(),GL_UNSIGNED_BYTE,dims[0],dims[1],functionProvider.getFunctionAddress("OSMesaMakeCurrent")); + } else if (System.getenv("POJAV_RENDERER").startsWith("opengles")) { // This fixed framebuffer issue on 1.13+ 64-bit by another making current - GLFW.nativeEglMakeCurrent(GLFW.mainContext); + GLFW.glfwMakeContextCurrent(GLFW.mainContext); if (isUsingRegal) { nativeRegalMakeCurrent(); } - } else if (System.getenv("RENDERER").contains("zink")) { - int[] dims = getNativeWidthHeight(); - callJPI(GLFW.glfwGetCurrentContext(),getGraphicsBufferAddr(),GL_UNSIGNED_BYTE,dims[0],dims[1],functionProvider.getFunctionAddress("OSMesaMakeCurrent")); } // We don't have a current ContextCapabilities when this method is called @@ -413,16 +413,10 @@ public final class GL { throw new IllegalStateException("There is no OpenGL context current in the current thread."); } - try { - APIVersion apiVersion = apiParseVersion(versionString); + APIVersion apiVersion = apiParseVersion(versionString); - majorVersion = apiVersion.major; - minorVersion = apiVersion.minor; - } catch (IllegalArgumentException e) { - e.printStackTrace(); - majorVersion = 2; - minorVersion = 1; - } + majorVersion = apiVersion.major; + minorVersion = apiVersion.minor; } } diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index 55226fb6..b35ba4ea 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -568,7 +568,7 @@ int launchJVM(int argc, char *argv[]) { char *userHome = calloc(1, 2048); char *memMin = calloc(1, 2048); char *memMax = calloc(1, 2048); - snprintf(frameworkPath, 2048, "-Djava.library.path=%s/Frameworks:%s/Frameworks/libOSMesaOverride.dylib.framework", getenv("BUNDLE_PATH"), getenv("BUNDLE_PATH")); + snprintf(frameworkPath, 2048, "-Djava.library.path=%s:%s/Frameworks:%s/Frameworks/libOSMesaOverride.dylib.framework", getenv("BUNDLE_PATH"), getenv("BUNDLE_PATH"), getenv("BUNDLE_PATH")); snprintf(javaPath, 2048, "%s/bin/java", javaHome); snprintf(jnaLibPath, 2048, "-Djna.boot.library.path=%s/Frameworks/libjnidispatch.dylib.framework", getenv("BUNDLE_PATH")); snprintf(userDir, 2048, "-Duser.dir=%s", getenv("POJAV_GAME_DIR")); @@ -625,8 +625,13 @@ int launchJVM(int argc, char *argv[]) { sprintf((char*) cacio_libs_path, "%s/libs_caciocavallo", getenv("BUNDLE_PATH")); cplen = sprintf(cacio_classpath, "-Xbootclasspath/p"); d = opendir(cacio_libs_path); + int skip = 2; if (d) { while ((dir = readdir(d)) != NULL) { + if (skip > 0) { + --skip; + continue; + } cplen += sprintf(cacio_classpath + cplen, ":%s/%s", cacio_libs_path, dir->d_name); } closedir(d); diff --git a/Natives/LauncherPreferencesViewController.m b/Natives/LauncherPreferencesViewController.m index 089e2f28..4c7e58e8 100644 --- a/Natives/LauncherPreferencesViewController.m +++ b/Natives/LauncherPreferencesViewController.m @@ -79,6 +79,7 @@ NSString *gl4es114 = @"GL4ES 1.1.4 - exports OpenGL 2.1"; NSString *gl4es115 = @"GL4ES 1.1.5 (1.16+) - exports OpenGL 2.1"; NSString *tinygl4angle = @"tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)"; NSString *zink = @"Zink (Mesa 21.0) - exports OpenGL 4.1"; +NSString *virglrenderer = @"virglrenderer - exports OpenGL 4.1"; NSString *java8jben = @"Java 8"; NSString *java16jben = @"Java 16"; NSString *java17jben = @"Java 17"; @@ -91,6 +92,7 @@ NSString *lib_gl4es114 = @"libgl4es_114.dylib"; NSString *lib_gl4es115 = @"libgl4es_115.dylib"; NSString *lib_tinygl4angle = @"libtinygl4angle.dylib"; NSString *lib_zink = @"libOSMesaOverride.dylib"; +NSString *lib_virglrenderer = @"libOSMesa.8.dylib"; int tempIndex; @@ -227,6 +229,9 @@ int tempIndex; } else if ([getPreference(@"renderer") isEqualToString:lib_zink]) { rendTextField.text = zink; tempIndex = 3; + } else if ([getPreference(@"renderer") isEqualToString:lib_virglrenderer]) { + rendTextField.text = virglrenderer; + tempIndex = 4; } rendTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentTop; @@ -238,6 +243,7 @@ int tempIndex; [rendererList addObject:gl4es115]; [rendererList addObject:tinygl4angle]; [rendererList addObject:zink]; + [rendererList addObject:virglrenderer]; rendPickerView = [[UIPickerView alloc] init]; rendPickerView.delegate = self; @@ -567,6 +573,8 @@ int tempIndex; setPreference(@"renderer", lib_tinygl4angle); } else if ([textField.text isEqualToString:zink]) { setPreference(@"renderer", lib_zink); + } else if ([textField.text isEqualToString:virglrenderer]) { + setPreference(@"renderer", lib_virglrenderer); } setenv("RENDERER", [getPreference(@"renderer") UTF8String], 1); diff --git a/Natives/egl_bridge.m b/Natives/egl_bridge.m index c2078d8f..c40dc5e1 100644 --- a/Natives/egl_bridge.m +++ b/Natives/egl_bridge.m @@ -66,8 +66,14 @@ EGLint (*eglGetError_p) (void); EGLContext (*eglCreateContext_p) (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); EGLBoolean (*eglSwapInterval_p) (EGLDisplay dpy, EGLint interval); EGLSurface (*eglGetCurrentSurface_p) (EGLint readdraw); + +int (*vtest_main_p) (int, const char*[]); +void (*vtest_swap_buffers_p) (void); +void* egl_make_current(void* window); + #define RENDERER_MTL_ANGLE 1 #define RENDERER_VK_ZINK 2 +#define RENDERER_VIRGL 3 int config_renderer; @@ -97,7 +103,7 @@ JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setenv(JNIEnv *en (*env)->ReleaseStringUTFChars(env, value, value_c); } -void terminateEgl() { +void pojavTerminate() { debug("EGLBridge: Terminating"); switch (config_renderer) { @@ -119,23 +125,57 @@ void terminateEgl() { } } -JNIEXPORT jlong JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglGetCurrentContext(JNIEnv* env, jclass clazz) { +void* pojavGetCurrentContext() { switch (config_renderer) { case RENDERER_MTL_ANGLE: - return (jlong) eglGetCurrentContext_p(); + return (void *)eglGetCurrentContext_p(); + case RENDERER_VIRGL: case RENDERER_VK_ZINK: - return (jlong) OSMesaGetCurrentContext_p(); + return (void *)OSMesaGetCurrentContext_p(); - default: return (jlong) 0; + default: return NULL; } } +void dlsym_EGL(void* dl_handle) { + eglBindAPI_p = dlsym(dl_handle,"eglBindAPI"); + eglChooseConfig_p = dlsym(dl_handle, "eglChooseConfig"); + eglCreateContext_p = dlsym(dl_handle, "eglCreateContext"); + eglCreateWindowSurface_p = dlsym(dl_handle, "eglCreateWindowSurface"); + eglDestroyContext_p = dlsym(dl_handle, "eglDestroyContext"); + eglDestroySurface_p = dlsym(dl_handle, "eglDestroySurface"); + eglGetConfigAttrib_p = dlsym(dl_handle, "eglGetConfigAttrib"); + eglGetCurrentContext_p = dlsym(dl_handle, "eglGetCurrentContext"); + //eglGetDisplay = replaced with eglGetPlatformDisplay + eglGetError_p = dlsym(dl_handle, "eglGetError"); + eglGetPlatformDisplay_p = dlsym(dl_handle, "eglGetPlatformDisplay"); + eglInitialize_p = dlsym(dl_handle, "eglInitialize"); + eglMakeCurrent_p = dlsym(dl_handle, "eglMakeCurrent"); + eglSwapBuffers_p = dlsym(dl_handle, "eglSwapBuffers"); + eglReleaseThread_p = dlsym(dl_handle, "eglReleaseThread"); + eglSwapInterval_p = dlsym(dl_handle, "eglSwapInterval"); + eglTerminate_p = dlsym(dl_handle, "eglTerminate"); + eglGetCurrentSurface_p = dlsym(dl_handle,"eglGetCurrentSurface"); +} + +void dlsym_OSMesa(void* dl_handle) { + OSMesaMakeCurrent_p = dlsym(dl_handle,"OSMesaMakeCurrent"); + OSMesaGetCurrentContext_p = dlsym(dl_handle,"OSMesaGetCurrentContext"); + OSMesaCreateContext_p = dlsym(dl_handle, "OSMesaCreateContext"); + OSMesaDestroyContext_p = dlsym(dl_handle, "OSMesaDestroyContext"); + OSMesaPixelStore_p = dlsym(dl_handle,"OSMesaPixelStore"); + glGetString_p = dlsym(dl_handle,"glGetString"); + glClearColor_p = dlsym(dl_handle, "glClearColor"); + glClear_p = dlsym(dl_handle,"glClear"); + glFinish_p = dlsym(dl_handle,"glFinish"); +} + void loadSymbols() { char fileName[2048]; switch (config_renderer) { case RENDERER_VK_ZINK: - sprintf((char *)fileName, "%s/Frameworks/libOSMesaOverride.dylib.framework/libOSMesaOverride.dylib", getenv("BUNDLE_PATH")); + sprintf((char *)fileName, "%s/Frameworks/%s.framework/%s", getenv("BUNDLE_PATH"), getenv("RENDERER"), getenv("RENDERER")); break; case RENDERER_MTL_ANGLE: sprintf((char *)fileName, "%s/Frameworks/MetalANGLE.framework/MetalANGLE", getenv("BUNDLE_PATH")); @@ -149,48 +189,54 @@ void loadSymbols() { } switch(config_renderer) { case RENDERER_VK_ZINK: - OSMesaMakeCurrent_p = dlsym(dl_handle,"OSMesaMakeCurrent"); - OSMesaGetCurrentContext_p = dlsym(dl_handle,"OSMesaGetCurrentContext"); - OSMesaCreateContext_p = dlsym(dl_handle, "OSMesaCreateContext"); - OSMesaDestroyContext_p = dlsym(dl_handle, "OSMesaDestroyContext"); - OSMesaPixelStore_p = dlsym(dl_handle,"OSMesaPixelStore"); - glGetString_p = dlsym(dl_handle,"glGetString"); - glClearColor_p = dlsym(dl_handle, "glClearColor"); - glClear_p = dlsym(dl_handle,"glClear"); - glFinish_p = dlsym(dl_handle,"glFinish"); + dlsym_OSMesa(dl_handle); break; case RENDERER_MTL_ANGLE: - eglBindAPI_p = dlsym(dl_handle,"eglBindAPI"); - eglChooseConfig_p = dlsym(dl_handle, "eglChooseConfig"); - eglCreateContext_p = dlsym(dl_handle, "eglCreateContext"); - eglCreateWindowSurface_p = dlsym(dl_handle, "eglCreateWindowSurface"); - eglDestroyContext_p = dlsym(dl_handle, "eglDestroyContext"); - eglDestroySurface_p = dlsym(dl_handle, "eglDestroySurface"); - eglGetConfigAttrib_p = dlsym(dl_handle, "eglGetConfigAttrib"); - eglGetCurrentContext_p = dlsym(dl_handle, "eglGetCurrentContext"); - eglGetError_p = dlsym(dl_handle, "eglGetError"); - eglGetPlatformDisplay_p = dlsym(dl_handle, "eglGetPlatformDisplay"); - eglInitialize_p = dlsym(dl_handle, "eglInitialize"); - eglMakeCurrent_p = dlsym(dl_handle, "eglMakeCurrent"); - eglSwapBuffers_p = dlsym(dl_handle, "eglSwapBuffers"); - eglReleaseThread_p = dlsym(dl_handle, "eglReleaseThread"); - eglSwapInterval_p = dlsym(dl_handle, "eglSwapInterval"); - eglTerminate_p = dlsym(dl_handle, "eglTerminate"); - eglGetCurrentSurface_p = dlsym(dl_handle,"eglGetCurrentSurface"); + dlsym_EGL(dl_handle); break; } } -JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglInit(JNIEnv* env, jclass clazz) { +void loadSymbolsVirGL() { + config_renderer = RENDERER_MTL_ANGLE; + loadSymbols(); + config_renderer = RENDERER_VK_ZINK; + loadSymbols(); + config_renderer = RENDERER_VIRGL; + + char fileName[2048]; + sprintf((char *)fileName, "%s/Frameworks/libvirgl_test_server.dylib.framework/libvirgl_test_server.dylib", getenv("BUNDLE_PATH")); + void *handle = dlopen(fileName, RTLD_LAZY); + NSLog(@"VirGL: libvirgl_test_server = %p", handle); + if (!handle) { + NSLog(@"VirGL: %s", dlerror()); + return; + } + vtest_main_p = dlsym(handle, "vtest_main"); + vtest_swap_buffers_p = dlsym(handle, "vtest_swap_buffers"); +} + +int pojavInit() { isInputReady = 1; mainThreadID = gettid(); - //const char *renderer = getenv("POJAV_RENDERER"); - //if (strncmp("opengles", renderer, 8) == 0) { NSString *renderer = @(getenv("RENDERER")); - if ([renderer hasPrefix:@"libgl4es"] || [renderer hasPrefix:@"libtinygl4angle"]) { + + if ([renderer isEqualToString:@"libOSMesa.8.dylib"]) { + config_renderer = RENDERER_VIRGL; + setenv("GALLIUM_DRIVER", "virpipe", 1); + loadSymbolsVirGL(); + } else if ([renderer hasPrefix:@"libgl4es"] || [renderer hasPrefix:@"libtinygl4angle"]) { config_renderer = RENDERER_MTL_ANGLE; loadSymbols(); + } else if ([renderer hasPrefix:@"libOSMesa"]) { + config_renderer = RENDERER_VK_ZINK; + setenv("GALLIUM_DRIVER","zink",1); + loadSymbols(); + } + + + if (config_renderer == RENDERER_MTL_ANGLE || config_renderer == RENDERER_VIRGL) { if (potatoBridge.eglDisplay == EGL_NO_DISPLAY) { potatoBridge.eglDisplay = eglGetPlatformDisplay_p(EGL_PLATFORM_ANGLE_ANGLE, (void *)EGL_DEFAULT_DISPLAY, NULL); if (potatoBridge.eglDisplay == EGL_NO_DISPLAY) { @@ -257,13 +303,27 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglInit(JNIEnv* env, j potatoBridge.eglDisplay, potatoBridge.eglSurface ); - return JNI_TRUE; + if (config_renderer != RENDERER_VIRGL) { + return JNI_TRUE; + } // } else if (strcmp(renderer, "vulkan_zink") == 0) { - } else if ([renderer hasPrefix:@"libOSMesa"]) { - config_renderer = RENDERER_VK_ZINK; - - setenv("GALLIUM_DRIVER","zink",1); - loadSymbols(); + } + + if (config_renderer == RENDERER_VIRGL) { + // Init EGL context and vtest server + const EGLint ctx_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; + EGLContext* ctx = eglCreateContext_p(potatoBridge.eglDisplay, config, NULL, ctx_attribs); + NSLog(@"VirGL: created EGL context %p", ctx); + + pthread_t t; + pthread_create(&t, NULL, egl_make_current, (void *)ctx); + usleep(100*1000); // need enough time for the server to init + } + + if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) { if(OSMesaCreateContext_p == NULL) { NSLog(@"OSMDroid: %s",dlerror()); return JNI_FALSE; @@ -286,7 +346,10 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglInit(JNIEnv* env, j int32_t stride; bool stopSwapBuffers; -void flipFrame() { +void pojavSwapBuffers() { + if (stopSwapBuffers) { + return; + } switch (config_renderer) { case RENDERER_MTL_ANGLE: { if (!eglSwapBuffers_p(potatoBridge.eglDisplay, potatoBridge.eglSurface)) { @@ -296,7 +359,12 @@ void flipFrame() { } } } break; - + + case RENDERER_VIRGL: { + glFinish_p(); + vtest_swap_buffers_p(); + } break; + case RENDERER_VK_ZINK: { glFinish_p(); dispatch_async(dispatch_get_main_queue(), ^{ @@ -305,54 +373,42 @@ void flipFrame() { } break; } } -JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglSwapBuffers(JNIEnv *env, jclass clazz) { - if (stopSwapBuffers) { - return JNI_FALSE; + +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) { + NSLog(@"EGLBridge: Error: eglMakeCurrent() failed: 0x%x", eglGetError_p()); + } else { + NSLog(@"EGLBridge: eglMakeCurrent() succeed!"); } - flipFrame(); - - return JNI_TRUE; + + if (config_renderer == RENDERER_VIRGL) { + NSLog(@"VirGL: vtest_main = %p", vtest_main_p); + NSLog(@"VirGL: Calling VTest server's main function"); + vtest_main_p(3, (const char*[]){"vtest", "--no-loop-or-fork", "--use-gles", NULL, NULL}); + } + + return NULL; } -JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglMakeCurrent(JNIEnv* env, jclass clazz, jlong window) { +void pojavMakeCurrent(void* window) { //if(OSMesaGetCurrentContext_p() != NULL) { // printf("OSMDroid: skipped context reset\n"); // return JNI_TRUE; //} - switch (config_renderer) { - case RENDERER_MTL_ANGLE: { + if (config_renderer == RENDERER_MTL_ANGLE) { EGLContext *currCtx = eglGetCurrentContext_p(); - NSLog(@"EGLBridge: Comparing: thr=%d, this=0x%llx, curr=%p", gettid(), window, currCtx); + NSLog(@"EGLBridge: Comparing: thr=%d, this=%p, curr=%p", gettid(), window, currCtx); if (currCtx == NULL || window == 0) { - /*if (window != 0x0 && potatoBridge.eglContextOld != NULL && potatoBridge.eglContextOld != (void *) window) { - // Create new pbuffer per thread - // TODO get window size for 2nd+ window! - int surfaceWidth, surfaceHeight; - eglQuerySurface(potatoBridge.eglDisplay, potatoBridge.eglSurface, EGL_WIDTH, &surfaceWidth); - eglQuerySurface(potatoBridge.eglDisplay, potatoBridge.eglSurface, EGL_HEIGHT, &surfaceHeight); - int surfaceAttr[] = { - EGL_WIDTH, surfaceWidth, - EGL_HEIGHT, surfaceHeight, - EGL_NONE - }; - potatoBridge.eglSurface = eglCreatePbufferSurface(potatoBridge.eglDisplay, config, surfaceAttr); - printf("EGLBridge: created pbuffer surface %p for context %p\n", potatoBridge.eglSurface, window); - }*/ - //potatoBridge.eglContextOld = (void *) window; - // eglMakeCurrent(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - NSLog(@"EGLBridge: Making current on window 0x%llx on thread %d", window, gettid()); - 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) { - NSLog(@"EGLBridge: Error: eglMakeCurrent() failed: 0x%x", eglGetError_p()); - } else { - NSLog(@"EGLBridge: eglMakeCurrent() succeed!"); - } + NSLog(@"EGLBridge: Making current on window %p on thread %d", window, gettid()); + egl_make_current((void *)window); // Test #ifdef GLES_TEST @@ -361,96 +417,70 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglMakeCurrent(JNIEnv* eglSwapBuffers(potatoBridge.eglDisplay, potatoBridge.eglSurface); NSLog(@"First frame error: 0x%x", eglGetError()); #endif - if (success == EGL_TRUE) { - void *gl4es_handle = dlopen(getenv("RENDERER"), RTLD_GLOBAL); - debug("%s=%p, error=%s", getenv("RENDERER"), gl4es_handle, dlerror()); - gl4esInitialize_func *gl4esInitialize = (gl4esInitialize_func*) dlsym(gl4es_handle, "initialize_gl4es"); - // debug("initialize_gl4es = %p", gl4esInitialize); - if (gl4esInitialize) { - gl4esInitialize(); - } else { - debug("%s", dlerror()); - } - debug("Renderer init success"); + // ADDITIONAL STEP ON IOS: Initialize gl4es + void *gl4es_handle = dlopen(getenv("RENDERER"), RTLD_GLOBAL); + debug("%s=%p, error=%s", getenv("RENDERER"), gl4es_handle, dlerror()); + + gl4esInitialize_func *gl4esInitialize = (gl4esInitialize_func*) dlsym(gl4es_handle, "initialize_gl4es"); + // debug("initialize_gl4es = %p", gl4esInitialize); + if (gl4esInitialize) { + gl4esInitialize(); + } else { + debug("%s", dlerror()); } + NSLog(@"Renderer init success"); - // idk this should convert or just `return success;`... - return success == EGL_TRUE ? JNI_TRUE : JNI_FALSE; + return; } else { // (*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); - return JNI_FALSE; + return; + } + } + + if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) { + NSLog(@"OSMDroid: making current"); + OSMesaMakeCurrent_p((OSMesaContext)window,gbuffer,GL_UNSIGNED_BYTE,savedWidth,savedHeight); + if (config_renderer == RENDERER_VK_ZINK) { + OSMesaPixelStore_p(OSMESA_ROW_LENGTH,savedWidth); + OSMesaPixelStore_p(OSMESA_Y_UP,0); } - } - - case RENDERER_VK_ZINK: { - NSLog(@"OSMDroid: making current"); - GLboolean result = OSMesaMakeCurrent_p((OSMesaContext)window,gbuffer,GL_UNSIGNED_BYTE,savedWidth,savedHeight); - //ANativeWindow_lock(potatoBridge.androidWindow,&buf,NULL); - OSMesaPixelStore_p(OSMESA_ROW_LENGTH, savedWidth); - //ANativeWindow_unlockAndPost(potatoBridge.androidWindow); - OSMesaPixelStore_p(OSMESA_Y_UP,0); NSLog(@"OSMDroid: vendor: %s",glGetString_p(GL_VENDOR)); NSLog(@"OSMDroid: renderer: %s",glGetString_p(GL_RENDERER)); NSLog(@"OSMDroid: extensions: %s",glGetString_p(GL_EXTENSIONS)); glClear_p(GL_COLOR_BUFFER_BIT); glClearColor_p(0.4f, 0.4f, 0.4f, 1.0f); - flipFrame(); - return result; - } + pojavSwapBuffers(); + return; } - return JNI_FALSE; + // should not reach here + NSLog(@"Error: Invalid renderer %d, aborting.", config_renderer); + abort(); } -JNIEXPORT void JNICALL -Java_org_lwjgl_glfw_GLFW_nativeEglDetachOnCurrentThread(JNIEnv *env, jclass clazz) { - //Obstruct the context on the current thread - - switch (config_renderer) { - case RENDERER_MTL_ANGLE: { - eglMakeCurrent_p(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - } break; - - case RENDERER_VK_ZINK: { - // Nothing to do here - } break; - } -} - -JNIEXPORT jlong JNICALL -Java_org_lwjgl_glfw_GLFW_nativeEglCreateContext(JNIEnv *env, jclass clazz, jlong contextSrc) { - switch (config_renderer) { - case RENDERER_MTL_ANGLE: { +void* pojavCreateContext(void* contextSrc) { + if (config_renderer == RENDERER_MTL_ANGLE) { const EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; EGLContext* ctx = eglCreateContext_p(potatoBridge.eglDisplay, config, (void*)contextSrc, ctx_attribs); - potatoBridge.eglContext = ctx; - NSLog(@"EGLBridge: Created CTX pointer = %p",ctx); //(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception"); - return (long)ctx; - } - - case RENDERER_VK_ZINK: { - NSLog(@"OSMDroid: generating context"); - void* ctx = OSMesaCreateContext_p(OSMESA_RGBA, (OSMesaContext)contextSrc); - NSLog(@"OSMDroid: context=%p",ctx); - return (jlong)ctx; - } + return (void *)ctx; } - return 0l; -} + if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) { + NSLog(@"OSMDroid: generating context"); + void* ctx = OSMesaCreateContext_p(OSMESA_RGBA,contextSrc); + NSLog(@"OSMDroid: context=%p",ctx); + return ctx; + } -JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglTerminate(JNIEnv* env, jclass clazz) { - isInputReady = 0; - terminateEgl(); - return JNI_TRUE; + return NULL; } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL_nativeRegalMakeCurrent(JNIEnv *env, jclass clazz) { @@ -475,17 +505,17 @@ Java_org_lwjgl_opengl_GL_getNativeWidthHeight(JNIEnv *env, jobject thiz) { (*env)->SetIntArrayRegion(env,ret,0,2,arr); return ret; } -JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_GLFW_nativeEglSwapInterval(JNIEnv *env, jclass clazz, jint interval) { + +void pojavSwapInterval(int interval) { switch (config_renderer) { - case RENDERER_MTL_ANGLE: { - return eglSwapInterval_p(potatoBridge.eglDisplay, interval); + case RENDERER_MTL_ANGLE: + case RENDERER_VIRGL: { + eglSwapInterval_p(potatoBridge.eglDisplay, interval); } break; - + case RENDERER_VK_ZINK: { NSLog(@"eglSwapInterval: NOT IMPLEMENTED YET!"); // Nothing to do here } break; } - - return JNI_FALSE; } diff --git a/Natives/resources/Frameworks/libOSMesa.8.dylib.framework/libOSMesa.8.dylib b/Natives/resources/Frameworks/libOSMesa.8.dylib.framework/libOSMesa.8.dylib index 8c7a816c..6891110a 100755 Binary files a/Natives/resources/Frameworks/libOSMesa.8.dylib.framework/libOSMesa.8.dylib and b/Natives/resources/Frameworks/libOSMesa.8.dylib.framework/libOSMesa.8.dylib differ diff --git a/Natives/resources/Frameworks/libglapi.0.dylib.framework/libglapi.0.dylib b/Natives/resources/Frameworks/libglapi.0.dylib.framework/libglapi.0.dylib index 84bd2b62..3c7c50d8 100755 Binary files a/Natives/resources/Frameworks/libglapi.0.dylib.framework/libglapi.0.dylib and b/Natives/resources/Frameworks/libglapi.0.dylib.framework/libglapi.0.dylib differ diff --git a/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/Info.plist b/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/Info.plist new file mode 100644 index 00000000..ca9f1a9c --- /dev/null +++ b/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + libvirgl_test_server.dylib + CFBundleIconFile + + CFBundleIdentifier + + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleShortVersionString + + CFBundleSignature + ???? + CFBundleVersion + + CSResourcesFileMapped + + + diff --git a/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/libvirgl_test_server.dylib b/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/libvirgl_test_server.dylib new file mode 100755 index 00000000..f207db35 Binary files /dev/null and b/Natives/resources/Frameworks/libvirgl_test_server.dylib.framework/libvirgl_test_server.dylib differ