Hi there, i'm trying to implement a Core for Libretro/Retroarch based on libgdx (eventually LWJGL). I asked for help on
libgdx forum and they suggested posting here too.
Premise:
Libretro/Retroarch is a generic "game system" that can execute "cores". Each core is an emulator, or a virtual machine (like there's a "Mame" core, a "dosbox" core, etc Doesn't need to be an emulator too, some games are relased as "cores" ). The infrastructure provides for all window and input management, the core has to specify its desired resolution and has a callback method to render the scene (simplifying a lot). Audio, input, etc are unified for all cores. Cores are actually just dll/so with specific callback functions (obviously they can rely on external files). Most important callbacks are "init" (that inizialize the core) and "run" (which is called every frame and should render the scene).
Also, cores come in two variant: the classic variant draw graphics on a generic "ram buffer" that's then sent to the screen (like old 8 bit system), while the opengl variant is opengl-aware and receive an opengl framebuffer onto which to render. (this is becouse opengl is so ubuquitous that they consider skipping a layer of abstraction for performances).
The main gotcha of the opengl core is that you have to render not on the screen but on a framebuffer that is provided to you by libretro infrastructure (so that it can render its own gui on top etc). This shouldn't be a huge deal since, once bound, rendering on the framebuffer should be pretty transparent.
So what i want to do is develop a Core that can run "java games". It would be a c dll/so program that: starts an embedded jvm, load some java "middleware" to setup the system, and then load a jar with a to-be-defined "game format", wiring all callbacks from libretro to methods on a java object.
Now as a proof of concept i was able to do most of the stuff: i took a libretro gl-core demo, added JVM management, loading a jar and calling methods during libretro various backcalls, including the "run" call that's done on each frame.
The problem is: any call to Opengl functions crash
Now, inside the java callback we should already be in a context where we can draw: there's a framebuffer bound and rendering ongoing. For reference, this is the C portion of the libretro demo that makes the java call:
...
...
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer());
glClearColor(0.3, 0.4, 0.5, 1.0);
glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
doJavaCall(); // here, the java side is called.
glUseProgram(prog);
glEnable(GL_DEPTH_TEST);
...
...
For the java side, i've tryed calling glClearColor and glClear again, with a different color to have something to actually verify that it's working. But as i said, it crashed.
Investigating, i ended up with the following code on the java side:
System.out.println("****************CHIAMATO DOCALL***************");
Configuration.DEBUG.set(true);
System.out.println("Context: "+WGL.wglGetCurrentContext());
System.out.println("Device: "+WGL.wglGetCurrentDC());
System.out.println("lolTest: "+org.lwjgl.opengl.GL11.class); // ensure class has initializers done
System.out.println("OK");
String s = org.lwjgl.opengl.GL11.glGetString(org.lwjgl.opengl.GL11.GL_VERSION);
System.out.println("Version is "+s);
Now this code, when i run retroarch, load the core and execute it, produces the following output:
calling doCall
****************CHIAMATO DOCALL***************
[LWJGL] Version: 3.2.3 SNAPSHOT
[LWJGL] OS: Windows 10 v10.0
[LWJGL] JRE: 13.0.1 amd64
[LWJGL] JVM: OpenJDK 64-Bit Client VM v13.0.1+9 by AdoptOpenJDK
[LWJGL] Loading JNI library: lwjgl
[LWJGL] Module: org.lwjgl
[LWJGL] Loaded from org.lwjgl.librarypath: C:\Users\niclugat\AppData\Local\Temp\lwjglniclugat\3.2.3-SNAPSHOT\lwjgl.dll
[LWJGL] Loading JNI library: lwjgl_opengl
[LWJGL] Module: org.lwjgl.opengl
[LWJGL] Loaded from org.lwjgl.librarypath: C:\Users\niclugat\AppData\Local\Temp\lwjglniclugat\3.2.3-SNAPSHOT\lwjgl_opengl.dll
[LWJGL] Loading library: opengl32
[LWJGL] Module: org.lwjgl.opengl
[LWJGL] opengl32.dll not found in org.lwjgl.librarypath=C:\Users\niclugat\AppData\Local\Temp\lwjglniclugat\3.2.3-SNAPSHOT
[LWJGL] Loaded from system paths: C:\WINDOWS\SYSTEM32\OPENGL32.dll
[LWJGL] Loading library: jemalloc
[LWJGL] Module: org.lwjgl.jemalloc
[LWJGL] Loaded from org.lwjgl.librarypath: C:\Users\niclugat\AppData\Local\Temp\lwjglniclugat\3.2.3-SNAPSHOT\jemalloc.dll
[LWJGL] MemoryUtil allocator: JEmallocAllocator
Context: 131072
Device: 251730347
lolTest: class org.lwjgl.opengl.GL11
OK
Now there's some output of LWJGL tellin that it's loading the library, and looks ok.
Then the two WGL calls actually works, and seems to tell that on the java side we actually ARE on a valid opengl context. After the "OK" log i've tryed many opengl calls and they all crash.
Now, since you guys are the wizards of dll loading, perhaps can help me.
My wild guess is that (since libretro is already up and running and lwjgl found all its natives) the java side is loading his own opengl dll and there's some kind of mismatch with what's already loaded and running on Libretro.
Also i found it strange that the WGL calls do indeed works, so i went to look at the sources and i'm under the impression that in LWJGL, WGL and GLxx uses two different approaches: WGL seems to be looking at function pointer and calling native "callPPI" style functions (this is black magic to me), while GL stuff seems to be using regular native functions like "static native void glClearColor" in GL11C. (can someone confirm this supposition?, Also, is there some docs on how all that magic works?)
If so, perhaps the first approach somehow bypass whatever issue is blocking the GL side.
So if anybody have some idea.. Does some "function pointer" styled GL wrapper exists ? Or can be created, perhapse just for glClearColor and glClear ?