Distributing GLES2 app on windows

Started by codifies, October 07, 2015, 16:56:11

Previous topic - Next topic

codifies

On Linux it's just a case of requiring the end user to install the GLES2 package and away you go...

however I'm not normally a windows user so I'm not terribly experienced with some of its ways... (I could be making more pain for myself than is required!)

regarding why ANGLE isn't bundled with LWJGL I'm told

That's outside the scope of LWJGL. There are other ways to use OpenGL ES on Windows, for example the WGL_EXT_create_context_es_profile extension and the AMD OpenGL ES SDK.

Does this mean I have to resort to code that specifically detects windows and uses WGL_EXT_create_context_es_profile (if so how?!) AND have to require an end user to download and install an SDK?

Ideally I'd just like have exactly the same Java code "just work" wherever it is, if I throw the appropriate 32/64 dll from the ANGLE project into the natives directory it does "just work" however then the installer would have to detect 32/64 bit and copy in the appropriate 32 or 64 bit dll (they have the same file name)

would adding the appropriate 32/64 bit ANGLE dll directory to the java library path work? how does one detect 32bit systems from a bat file?

I'm wanting the most transparent method to the code but that is also easy for a none technical end user

spasi

Quote from: codifies on October 07, 2015, 16:56:11That's outside the scope of LWJGL. There are other ways to use OpenGL ES on Windows, for example the WGL_EXT_create_context_es_profile extension and the AMD OpenGL ES SDK.

Does this mean I have to resort to code that specifically detects windows and uses WGL_EXT_create_context_es_profile (if so how?!) AND have to require an end user to download and install an SDK?

What I meant was that using ANGLE is a viable approach, but not the only one. LWJGL shouldn't force a particular approach to its users. You can still use ANGLE, just like other users might want to use Regal or any other wrapper. LWJGL doesn't care and will use any compatible library.

Quote from: codifies on October 07, 2015, 16:56:11if I throw the appropriate 32/64 dll from the ANGLE project into the natives directory it does "just work" however then the installer would have to detect 32/64 bit and copy in the appropriate 32 or 64 bit dll (they have the same file name)

would adding the appropriate 32/64 bit ANGLE dll directory to the java library path work? how does one detect 32bit systems from a bat file?

The default library names (and paths) in LWJGL can be changed dynamically at runtime. One approach would be:

- Distribute your application with the ANGLE .dlls
- The 32/64-bit .dlls should be named differently if you want to put them in the same directory. LWJGL uses the default name for the 64-bit binary and adds a "32" postfix for the 32-bit one, i.e. you could use libEGL.dll and libEGL32.dll.
- Before initializing EGL/GLES, set the appropriate library names using the org.lwjgl.system.Configuration class. For example:

Configuration.LIBRARY_NAME_EGL.set(Pointer.BITS64 ? "libEGL" : "libEGL32");


Another approach would be to use the default name for both architectures and put the .dlls in separate directories. Then:

Configuration.LIBRARY_PATH.set("mylibpath/" + (Pointer.BITS64 ? "x64" : "x86"));

codifies

That's a *lot* more configurable than I thought it would be! - I guess I'd still need specific code to detect and support windows though?

spasi

Yes, if the above applies to Windows only, you can wrap everything in:

if ( LWJGLUtil.getPlatform() == Platform.WINDOWS ) {
    // Windows-specific configuration
}

codifies

okay thats bearable ;) ANGLE seems to be using gigs of stack and direct buffer space and making a black on black image.... so I guess the two year old binary from opentk dependencies isn't the way to go!

I need to investigate regal does it wrap EGL as well as GLES  - I'll have to suck it and see

after literally 40 mins of updates and 4 reboots (I kid you not) I just found out that my "free" version of visual studio has expired - so no sure what I'm going to do about supporting windows - its just such a painful experience!

spasi

Quote from: codifies on October 08, 2015, 11:44:30I just found out that my "free" version of visual studio has expired - so no sure what I'm going to do about supporting windows - its just such a painful experience!

Get VS 2015 Community Edition. Has been painless for me so far and offers much more than the old Express editions.

codifies

yeah that's what says its expired? I'll have another go once I can bare dealing with windows again...

codifies

I did try
Configuration.LIBRARY_NAME_GLES.set("opengl32");

and replacing the window hint (for glfw) with the opengl api flag

These are things that could be done with very simple run time windows detection

my hope here was that I could develop on machines that had a "real" GLESv2 library but have it work unmodified on a windows machine. You'd have the "protection" of a GLES 2.0 profile stopping doing something that wouldn't work on embedded Linux systems but that would also work on windows - a kind of truly universal binary!

alas something wants to load EGL as well ( wouldn't this happen if I tried Regal ? )

The actual "demo" code I was using does work fine if I replace the GLES headers with various GL1.1 1.3 1.5 2.0 imports but obviously thats a recompile.... (but it is nice to confirm that GLES2 is a *working* subset of OpenGL2 !!!)

Is there anyway to implicit stop EGL from being used? (I suspect its something in GLES or GLES2 classes triggering the loading of the EGL dll and not the glfw class)

codifies

is this a bug?

in GLES.java
Quote
   public static void create(String libName) {
      final DynamicLinkLibrary GLES = LWJGLUtil.loadLibraryNative(libName);

      try {
         FunctionProvider functionProvider = new FunctionProvider.Default() {
            @Override
            public long getFunctionAddress(CharSequence functionName) {
               APIBuffer __buffer = apiBuffer();
               __buffer.stringParamASCII(functionName, true);

               long address = EGL.getFunctionProvider().getFunctionAddress(functionName);
               if ( address == NULL ) {
                  address = GLES.getFunctionAddress(functionName);

shouldn't this be
Quote
   public static void create(String libName) {
      final DynamicLinkLibrary GLES = LWJGLUtil.loadLibraryNative(libName);

      try {
         FunctionProvider functionProvider = new FunctionProvider.Default() {
            @Override
            public long getFunctionAddress(CharSequence functionName) {
               APIBuffer __buffer = apiBuffer();
               __buffer.stringParamASCII(functionName, true);

               long address = GLES.getFunctionProvider().getFunctionAddress(functionName);
               if ( address == NULL ) {
                  address = GLES.getFunctionAddress(functionName);

spasi

No, it isn't. Loading a GLES function goes through EGL because it provides eglGetProcAddress. This is the cross-platform alternative to wglGetProcAddress & glXGetProcAddress.

I see what you're trying to do though. Try this:

Configuration.EXPLICIT_INIT_OPENGLES.set(true);

GLES.create(GL.getFunctionProvider()); // omg?!

GLESCapabilities caps = GLES.createCapabilities();

System.out.println(GLES20.glGetString(GLES20.GL_VERSION));
System.out.println("GLES20 = " + caps.GLES20);
System.out.println("GLES30 = " + caps.GLES30);
System.out.println("GLES31 = " + caps.GLES31);
System.out.println("GLES32 = " + caps.GLES32);

This seems to work for me. GLES32 returns false, but that's an unrelated bug that will be fixed in the next nightly build.

codifies

HAha ! ya genius!

works like a charm.... I get actual graphical output on windows, and on Linux the class's compiled on a windows box just happily worked with libGLESv2.so;D oh happy days!

I have to be honest and say I had to read
GLES.create(GL.getFunctionProvider()); // omg?!
twice until I appreciated your cunning !

using this "cheat" I can be fairly confident something I develop on a Linux box or on say an Open Pandora (or Pyra, sooon my pretty soon!) and be reasonable confident the compiled "binary" will work even on most windows boxes (assuming a JRE - but that can be detected and warned about or even bundled...)

just one tiny fly in the ointment (good grief is this man never happy!)

does
/** Loads the OpenGL ES native library, using the default library name. */
	public static void create() {
		String libName;
		switch ( LWJGLUtil.getPlatform() ) {
			case LINUX:
				libName = "GLESv2";
				break;
			case MACOSX:
				throw new UnsupportedOperationException("MacOS X does not support OpenGL ES");

this mean that this technique wont work on MacOS X ? ie compile as if a GLES2.0 application but dynamically link to what ever MacOS X uses for OpenGL ?

I'm going to tidy up my code and write up some notes and make a blog post about this, in case others might find it useful (I'll post the url here)  Its a testament to the flexibility of the internals of LWJGL that my (ab)uses like this are even possible!

spasi

Quote from: codifies on October 09, 2015, 15:31:26this mean that this technique wont work on MacOS X ? ie compile as if a GLES2.0 application but dynamically link to what ever MacOS X uses for OpenGL ?

Nope, setting EXPLICIT_INIT_OPENGLES to true bypasses the default create() method.

Quote from: codifies on October 09, 2015, 15:31:26Its a testament to the flexibility of the internals of LWJGL that my (ab)uses like this are even possible!

That was one of the explicit goals of the LWJGL 3 redesign. Be easy to use like LWJGL 2, but at the same time be even more lightweight and not get in the user's way when they want customization. Though, I'm pretty surprised myself that the above solution actually works. :)

Cornix

Quote from: spasi on October 09, 2015, 15:39:58
Quote from: codifies on October 09, 2015, 15:31:26this mean that this technique wont work on MacOS X ? ie compile as if a GLES2.0 application but dynamically link to what ever MacOS X uses for OpenGL ?

Nope, setting EXPLICIT_INIT_OPENGLES to true bypasses the default create() method.

Quote from: codifies on October 09, 2015, 15:31:26Its a testament to the flexibility of the internals of LWJGL that my (ab)uses like this are even possible!

That was one of the explicit goals of the LWJGL 3 redesign. Be easy to use like LWJGL 2, but at the same time be even more lightweight and not get in the user's way when they want customization. Though, I'm pretty surprised myself that the above solution actually works. :)

I dont know how it makes me feel to hear a developer is surprised his software actually works.

spasi

Quote from: Cornix on October 09, 2015, 17:15:54I dont know how it makes me feel to hear a developer is surprised his software actually works.

The surprising bit is using the OpenGL library to initialize the OpenGL ES bindings. This use case had not even occurred to me before reading codifies' posts.

codifies

I've written this up as clearly as I can, what the solution is for, how it works, and also included a code sample

http://bedroomcoders.co.uk/gles2-0-everywhere-thanks-to-lwjgl3/