We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2570 - SDL uses ES2_compatibility when available - causes very mysterious failure to draw on some systems
Summary: SDL uses ES2_compatibility when available - causes very mysterious failure to...
Status: ASSIGNED
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: HG 2.0
Hardware: x86_64 Other
: P2 blocker
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords: target-2.0.6
Depends on: 3145
Blocks: 3725
  Show dependency treegraph
 
Reported: 2014-06-05 08:56 UTC by Mark Callow
Modified: 2017-08-16 00:22 UTC (History)
3 users (show)

See Also:


Attachments
Patch to add SDL_GL_ES_IMPLEMENTATION_PREFERENCE attribute (4.73 KB, text/plain)
2014-06-10 10:05 UTC, Mark Callow
Details
Add compile option to disable hidden use of ARB_ES2_compability (2.87 KB, patch)
2014-11-13 02:32 UTC, Mark Callow
Details | Diff
Fixes bugs 2570 & 3145 (19.41 KB, patch)
2015-12-11 11:10 UTC, Mark Callow
Details | Diff
Fixes bugs 2570 and 3145, works on X11 (19.75 KB, patch)
2015-12-30 04:51 UTC, Mark Callow
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Callow 2014-06-05 08:56:17 UTC
When an application specifies SDL_GL_CONTEXT_PROFILE_ES and is running on Windows (possibly also Linux, I haven't checked) SDL will use ARB_ES2_compatibility, when available, otherwise it loads libGLESv2.dll & libEGL.dll. This leads to an application running fine on some systems while failing to draw on others. A detailed explanation is given in the following forum message. 

http://forums.libsdl.org/viewtopic.php?t=10236&sid=8783661a52151c6a1f9e199369717343

The main issue is that when building an OpenGL ES2 application using the standard Khronos headers and linking against a typical libGLESv2 library, such as ANGLE's, function calls are resolved at link time. A developer can successfully run the application on his machine but it will break on someone else's because they have a different graphics card.

I have hacked my copy of SDL to workaround the problem by commenting out line 290 in SDL_windowswindow.c

#if SDL_VIDEO_OPENGL_ES2
    if ((window->flags & SDL_WINDOW_OPENGL) &&
        _this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
#if SDL_VIDEO_OPENGL_WGL           
        // && (!_this->gl_data || !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile)
#endif

and commenting out most of line 587 in SDL_windowsopengl.c

    if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES /*&&
        !_this->gl_data->HAS_WGL_EXT_create_context_es2_profile*/) { 

Clearly a hack. Real fixes are

1. Fix up the function calls automatically when using ARB_ES2_compatibility.
2. Add a context profile or context flag that says always use libGLESv2.dll.
3. Document that when using ES2, the app must use GetProcAddress.

I favour #2. #1 is not possible without access to the GL ES implementation innards. #3 is a pain because (a) most platforms supporting ES do not require run time proc. address queries for core functions and (b) you have to write your own declarations for pointers for most of the core functions rather than use the function declarations in GLES/gl2.h.

Whatever solution is chosen, the way of using OpenGL ES and especially ANGLE with SDL needs to be properly documented.
Comment 1 Mark Callow 2014-06-05 10:07:20 UTC
I forgot to note that there are reasons why an application might want to use the libGLESv2.dll even when compatibility is available such as testing with a ANGLE or a specific ES2 emulator. This argues for solution #2.
Comment 2 Gabriel Jacobo 2014-06-06 19:58:08 UTC
I'm marking this as wontfix because this is the way SDL works by design...and it does so like this in all platforms.

If you want to link statically to libGLESv2, you may be able to do so only on Windows with ANGLE because ANGLE abstracts you from the hardware by using Direct3D, but it won't work on Linux at all, i.e. if you compile on an nVidia based system it won't work on Mesa based systems.

Your point about adding documentation for this is valid. There's some comments in https://wiki.libsdl.org/SDL_GL_GetProcAddress but if you have other ideas on how to document this pitfall let me know.

All that said, if you want to link statically to ANGLE, it's perfectly valid to customize SDL for that.
Comment 3 Mark Callow 2014-06-10 06:22:38 UTC
My application works fine on iOS using, to borrow your phrase, "static linking."* All of the emulators from the various vendors of OpenGL ES IP also support static linking. Mesa (or possibly its Intel) provides an EGL + OpenGL ES implementation for Linux which I expect also supports static linking. Note, this is different from ARB_ES*_compatibility.

[* Let's clear up one piece of confusion. This is not static linking in the usual sense. The application may well be linking to a dynamic library. In this case we mean that linking with the library satisfies the function call references.]

So there may be many reasons why an app. writer chooses not to go to the trouble of defining a bunch of function pointers and loading all the addresses at run-time. This argues for a context flag so the app. can indicate its preference. It may need as many as 3 values:

- require OpenGL ES
- prefer OpenGL ES
- prefer ARB_ES_compatibility

I will customize my copy of SDL like this.

As for the documentation, when I did a search for information about using SDL 2 with OpenGL ES & EGL, IIRC I found nothing much on libsdl.org. I found an example elsewhere that said to specify SDL_GL_CONTEXT_EGL and SDL_GL_CONTEXT_PROFILE_ES. However looking at the source code though the other day, I saw SDL_GL_CONTEXT_EGL has been deprecated. The rest of what I did was based on my experience writing native OpenGL ES applications.

I think libsdl.org needs a Wiki page that explains if you specify SDL_GL_CONTEXT_PROFILE_ES, SDL will first try ARB_ES_compatibility. If that is not available it will try to load libGLESv2.dll (and several variants). It also needs to say that applications must load the function call addresses themselves for both of these cases to work. It can also warn that if you link the application against libGLESv2.lib instead of loading function addresses that the app will work in the cases when libGLESv2.dll is loaded but fail when ARB_ES_compatbility is used.

Of course I would like it if you would add a context flag as detailed above.

BTW, beware ARB_ES_compatibility when you come to add support for OS X 10.9. Because Apple supports OpenGL core profile only, certain features vital to the operation of OpenGL ES programs are missing. The worst case is for ES2.
Comment 4 Mark Callow 2014-06-10 10:05:25 UTC
Created attachment 1678 [details]
Patch to add SDL_GL_ES_IMPLEMENTATION_PREFERENCE attribute
Comment 5 Mark Callow 2014-06-10 10:07:46 UTC
Sometimes I hate Bugzilla. It threw away the comment I was making when I clicked add an attachment. Here it is again...

I made a patch along the lines I described in comment #3. I am attaching it, in case you decide its useful. However I realized that for my current purpose it is easier to simply compile SDL to use only EGL & OpenGL ES. But when I set the #defines appropriately for that SDL does not compile. I have created a patch to fix that which can be found in bug #2579 and I have my app. working with the patch.
Comment 6 Mark Callow 2014-11-13 02:30:56 UTC
I have made a patch that adds a new define SDL_VIDEO_ALWAYS_USE_ES_FOR_ES which when set disables the behavior of using ARB_ES2_compatibility on (some) Windows systems. I will attach the patch after this comment.

I am reopening the bug to have this patch applied to the source. Currently the patch is only for Windows. I do not know if it should be appended to the config files for other platforms.

I recommend that the default binaries distributed for Windows be compiled with this option set because the silent use of ARB_ES2_compatibility is NOT transparent to the application.

I need this because the Open ES driver for my apps does not load the symbols at runtime as Windows is the only platform, so far, where that would be necessary. However I have starting using the dll also with version of my apps that use OpenGL so I need OpenGL context support. The patch I provided in bug #2579 was great until I needed OpenGL support too.
Comment 7 Mark Callow 2014-11-13 02:32:58 UTC
Created attachment 1931 [details]
Add compile option to disable hidden use of ARB_ES2_compability

I am not obsoleting patch 1678 because that provides a runtime way to disable the hidden use while the latest patch provides a compile time way.
Comment 8 Gabriel Jacobo 2014-11-13 03:13:25 UTC
If a decision is made to allow the user to choose how the ES context is created (something currently unsupported by design), it won't be with a hardcoded Windows only design.
As mentioned before, if this suits your needs it seems something that you can very easily do by patching and building your own binaries.

Thanks!
Comment 9 Mark Callow 2014-11-13 04:12:00 UTC
As I have noted repeatedly, this choice is not transparent the application and is therefore a problem. The application even needs to be compiled with a non-standard header, as the standard Khronos header declares all the GL entry points as functions. To work with ARB_ES_compability the app must declare them as pointers and must initialize them at startup. While this is typical practice for OpenGL, it is something I have never needed to do in twelve years of working with real OpenGL ES implementations.

So this is an issue that needs to be fixed.

I would at the very least like my latest patch included in the source so I don't have to keep patching new releases. With the new define set to 0, there is no change in behavior from today.

You describe this as a "hardcoded windows design" but so far Windows is the only platform on which I have encountered this problem (app failing when on ARB_ES2_compatibility). It works fine on Mac with an OpenGL 4.1 context so obviously the static linking works there. I haven't tried Linux. It's a non issue for iOS and Android as they have real OpenGL ES implementations.
Comment 10 Mark Callow 2014-11-18 06:25:44 UTC
If this stays as WONTFIX it will get lost...

In comment #s 6 & 7, I am not asking for the default binaries to be compiled with SDL_VIDEO_ALWAYS_USE_ES_FOR_ES defined as 1, only for the code to be included in the source.

Regardless of the decision re. the above, the issue of OpenGL ES apps failing to run on certain platforms with certain graphics cards does need to be fixed. This ticket can serve to keep than on the TODO list.
Comment 11 Mark Callow 2014-11-18 06:27:15 UTC
"than on" -> "that on".
Comment 12 Mark Callow 2015-10-09 23:38:01 UTC
Please note that SDL is looking for WGL_EXT_create_context_es2_profile not GL_ARB_ES2_compatibility. So please s/ARB_ES2_compatibility/WGL_EXT_create_context_es2_profile/ in the description and all previous comments.

There is another issue closely related to this that I have just found. See bug #3145.

This bug continues to be a huge nuisance. Applications have a choice of always compiling using GLEW (or equivalent) and always loading all the symbols at run-time or somehow detecting that SDL has given them an OpenGL context and refusing to run.

It also means that applications cannot use any of the OpenGL ES emulators on Windows (such as from ARM, Imagination and Qualcomm) because SDL will give them the an OpenGL context.
Comment 13 Mark Callow 2015-10-09 23:47:51 UTC
I am willing to look into fixing this and 3145 but I need to know that my contribution will not be ignored like my previous patches to this bug and the very nice script I contributed in bug #2839 to build Android libraries.

Also please tell me where I can find the HG 2.1 listed in bugzilla's version field. I can't see any such branch in http://hg.libsdl.org/. I don't want to be working with outdated code.
Comment 14 Mark Callow 2015-10-29 09:18:19 UTC
Another way to fix this, besides an SDL_GL_ES2_DRIVER_PREFERENCE attribute, is a variant on SDL_GL_LoadLibrary. I tried

    SDL_GL_LoadLibrary("libGLESv2.dll")

but, sadly, the function expects only to be asked to load an OpenGL library and fails when it can't find functions like {wgl,glx}GetProcAddress.

I am thinking of adding either an SDL_GLES_LoadLibrary or a variant SDL_GL_LoadLibrary that takes a flag saying whether to load GL or GLES. Which do the gods of SDL think is better: specifying the desired library up front or a config attribute expressing the preference.

One advantage of the LoadLibrar approach is that it is independent of the fix for bug #3145.

The only platforms currently where {WGL,GLX}_EXT_create_context_es2_profile is used in preference to libGLESv2 are X11 (on Linux and Mac) and Windows. I will apply the fix to both of those platforms.

The OpenGL ES emulators from the likes of ARM, Imagination and Qualcomm have Windows and Linux versions. Applications using those, as well as ANGLE, can benefit from this problem being solved as they can be sure what implementation they are using.

Also notable is that there will soon be ANGLE for Linux and OS X and Imagination has an OS X version of its emulator. Perhaps GLES support should be extended to OS X but that should be a separate RFE.
Comment 15 Mark Callow 2015-12-11 11:10:19 UTC
Created attachment 2335 [details]
Fixes bugs 2570 & 3145

The attached patch does the following for the X11 and Windows platforms, the only ones where SDL attempts to use context_create_es_profile:

- Adds SDL_HINT_OPENGL_ES_DRIVER by which the application can
  say to use the OpenGL ES driver & EGL rather than the Open GL
  driver. (For bug #2570)
- Adds code to {WIN,X11}_GL_InitExtensions to determine the maximum
  OpenGL ES version supported by the OpenGL driver (for bug #3145)
- Modifies the test that determines whether to use the OpenGL
  driver or the real OpenGL ES driver to take into account the
  hint, the requested and supported ES version and whether ES 1.X
  is being requested. (For bug #2570 & bug #3145)
- Enables the testgles2 test for __WINDOWS__ and __LINUX__ and adds
  the test to the VisualC projects.

With the fix in place I have run testdraw2, testgl and testgles2 without any issues and have run my own apps that use OpenGL, OpenGL ES 3 and OpenGL ES 1.1.

I created a fork of SDL with this patch in place at https://github.com/msc-/SDL.

The hint that fixes #2570 is an innocuous change that will have no effect on applications not using it. The other changes for #3145 are important for using modern versions of OpenGL ES.
Comment 16 Mark Callow 2015-12-30 04:51:00 UTC
Created attachment 2351 [details]
Fixes bugs 2570 and 3145, works on X11

This replacement patch fixes compile errors in the X11 platform changes. The X11 changes have now been compiled and tested on Ubuntu 14.04. The WIN changes were previously tested.

These errors were in the first patch because I mistakenly thought the relevant files were being compiled by the Xcode project that included them. However they contain #if's bracketing the entire code which are not defined for the default Mac build.
Comment 17 Carles Pagès 2017-01-10 09:34:12 UTC
Fwiw, I also had to patch sdl to force angle usage, before finding this ticket. It still applies (except for the vcproj changes) and seems to work fine, so would be nice to get this functionality/fixes in.
Comment 18 Sam Lantinga 2017-01-10 16:57:54 UTC
This is in now, thanks Mark!
https://hg.libsdl.org/SDL/rev/36f40b8cc979

I made a few tweaks to the patch, in particular the spec says that WGL/GLX_EXT_create_context_es2_profile must advertise WGL/GLX_EXT_create_context_es_profile as well, so checking either string is sufficient, and if WGL/GLX_EXT_create_context_es2_profile is present then GLES 2.0 is supported. Please let me know if I broke anything!
Comment 19 Mark Callow 2017-01-11 06:35:38 UTC
I am delighted this has finally been included in SDL.

Your change is functionally equivalent to my original. I chose my way to avoid the 3 somewhat heavy SDL_GL_ExtensionSupported calls that are not needed when only ES2 profiles are supported and because I find references to {GLX,WGL}_EXT_create_context_es2_profile in places dealing with 3.x profiles a tad confusing.
Comment 20 Sam Lantinga 2017-08-04 20:07:44 UTC
The fix to this bug introduced bug 3725
Comment 21 Mark Callow 2017-08-16 00:22:54 UTC
(In reply to Sam Lantinga from comment #20)
> The fix to this bug introduced bug 3725

Actually it was the fix for bug 3145, which happened to be included in the patch attached to this bug.