DerelictGLES 0.0.1

Quite a while back, Ben Boeckel put together a binding for OpenGLES 2. It’s been sitting in the DerelictOrg group ever since, but hasn’t been in the DUB registry. Also, it only had support for loading on Linux.

Recently, when I had some downtime from the book, I decided to spend it trying to get Google’s Angle project working with DerelictGLES. Toward that end, I added some missing support for Windows, including the loading of libegl.dll and libglesv2.dll. Then I decided to try to get it working with SDL.

Long story short, when creating a window with a GLES context, SDL tries first to load everything via the graphics driver and will only load Angle if that fails. The only way to force it to use Angle is to create the EGL context yourself, then pass the window handle to SDL_CreateWindowFrom. I haven’t gone that route yet. Instead, I wanted to get it working with SDL’s context creation.

The problem is that DerelictGL.load will only load the Angle shared library, so if SDL is using the driver’s GLES2 implementation, then there are two different implementations loaded in memory and nothing is going to work. Since there’s no way to force SDL to use Angle, and since the drivers do not have a common name for their GLES DLLs, I opted to add a new load method to DerelictGLES that takes a pointer to a symbol loading function. An implementation for SDL looks like this:

void* loadSymbol(string name) {
    import derelict.util.exception : SymbolLoadException;
    import std.format : format;

    auto sym = SDL_GL_GetProcAddress(name.ptr);
    if(!sym) throw new SymbolLoadException(format("Failed to load symbol %s: %s",
        to!string(SDL_GetError())));
    return sym;
}

With that, using DerelictGLES with SDL looks like this:

DerelictSDL2.load();
if(SDL_Init(SDL_INIT_VIDEO) == -1) throw new Error("Failed to init SDL: " ~
    to!string(SDL_GetError()));

// Configure SDL to use OpenGLES2.
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

// This line is optional. If you have Angle (libegl.dll and libglesv2.dll)
// on the library path, SDL will try to load it if the driver does not support
// GLES2. When they are the same binaries that ship with Chrome, Angle requires the
// that d3dcompiler_47.dll be preloaded. With custom-built Angle binaries, this
// requirement can be turned off. If you do want to use Angle as a fallback, this
// needs to be called before creating the window.
SDL_SetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER, "d3dcompiler_47.dll");

window = SDL_CreateWindow("Hello Triangle",
    SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
    winWidth, winHeight, SDL_WINDOW_OPENGL);
if(!window) throw new Error("Failed to create window: " ~
    to!string(SDL_GetError()));

context = SDL_GL_CreateContext(window);
if(!context) throw new Error("Failed to create GLES context: " ~
    to!string(SDL_GetError()));
SDL_GL_MakeCurrent(window, context);

DerelictGLES2.load(&loadSymbol);
writeln(to!string(glGetString(GL_VENDOR)));
writeln(to!string(glGetString(GL_VERSION)));

Using this approach, it’s important that DerelictGLES.load be called *after* creating the window and the context. The benefit is that no matter which GLES2 implementation SDL has loaded, the binding will be tapped in to it. I have tested this using the Hello Triangle example from the OpenGL ES 2.0 Programming Guide on Windows. It compiles and runs fine, reporting that it’s using NVidia’s implementation.

This approach to loading should also work with GLFW. It supports GLES already and should have Angle support in version 3.2.

If you’re interested in using this, please give it a spin yourself and see if it breaks for you. Currently, only Linux and Windows are supported. I have a Mac and have no idea what GLES support is like on OSX, so there’s no support for it whatsoever at the moment. I’ve seen some Mac stuff in the Angle headers, though, but I have no idea what that’s about.

DerelictSFML2 2.0.0

I’ve updated DerelictSFML2 to support CSFML 2.2. In the process, I’ve added support for SharedLibVersion, so the same loaders can now load CSFML 2.0, 2.1, and 2.2. For example, to guarantee 2.0 will load, no matter the version of the CSFML shared libraries, you can do the following.

auto slv = SharedLibVersion(2, 0, 0);
DerelictSFML2Audio.load(slv);
DerelictSFML2Graphics.load(slv);
DerelictSFML2Network.load(slv);
DerelictSFML2System.load(slv);
DerelictSFML2Window.load(slv);

The tag to use for your DUB dependencies is derelict-sfml2 2.0.0.

DerelictFI 2.0.1

This is what I get for not having tests set up for loading every shared library in every circumstance. I realized when I went to bed last night that I had incorrectly implemented SharedLibVersion support for DerelictFI, causing it to do the wrong thing. I guess it’s been so long since I touched the code I had forgotten how it was intended to be used. I had to wait until I came home from work today to fix it, but now 2.0.1 is tagged and the DUB repository should pick it up shortly. This is now the corrected list of possible minimum versions for DerelictFI and they should all work as expected.

// Allow versions 3.15.0+
DerelictFI.load(SharedLibVersion(3, 15, 0));
// Allow versions 3.15.4+
DerelictFI.load(SharedLibVersion(3, 15, 4);
// Allow versions 3.16.0+
DerelictFI.load(SharedLibVersion(3, 16, 0));
// Allow versions 3.17.0+
DerelictFI.load(SharedLibVersion(3, 17, 0));
// Allow only the highest supported version -- Currently 3.17.0
DerelictFI.load();

DerelictFI 2.0.0 Supports FreeImage 3.17.0

I’ve updated DerelictFI, the FreeImage binding. It now supports up to 3.17.0 (previously it only supported 3.15.4). By default, it will load version 3.17.0 of the FreeImage shared library and will error out on older versions. However, this release also supports the SharedLibVersion feature of DerelictUtil 2.0, so you all of the following are valid:

// Allow versions 3.15.0+
DerelictFI.load(SharedLibVersion(3, 15, 0));
// Allow versions 3.16.0+
DerelictFI.load(SharedLibVersion(3, 16, 0));
// Allow versions 3.17.0+
DerelictFI.load(SharedLibVersion(3, 17, 0));
// Allow only the highest supported version -- Currently 3.17.0
DerelictFI.load();

To make use of these features, update your DUB dependency to “derelict-fi”: “>=2.0.0″. From here on out, development will happen in master and merged into the new 2.0 branch when ready for release. Note that I’ve only verified that this compiles and haven’t had the chance to test out the new stuff yet, so if you find any problems please report them in the issue tracker.

DerelictUtil 2.0.0

I’m taking some time away from my priority project to chip away a little at my Derelict TODO list. As part of that, I’ve just merged the 2.0 branch of DerelictUtil with master and tagged a 2.0.0 release. The plan going forward is that all development will happen on master and merged into the 2.0 branch when it’s ready to tag.

For many Derelict users, this change shouldn’t have any negative impact. Most projects should still compile and work without change. There are, however, two potential pain points.

People using DUB to manage their projects will largely be safe except in the case when they are mixing  bindings that use >=, ~>, or == in their dependency on DerelictUtil.  For example, a project with the dependency derelict-util: >=1.0.0” will always pick up the latest version when updated or first pulled down by DUB, but a project with the dependency “derelict-util”: “==1.0.0” will always get version 1.0.0 of DerelictUtil. 2.0.0 is not binary compatible with 1.0.0. At the moment, I’m not sure if DUB goes with the lowest-common-denominator in that case, but ==2.0.0 will certainly conflict with ==1.0.x. As far as I know, most, if not all, of the packages in DerelictOrg use the >= format (I’m not the primary maintainer of every package there and haven’t checked all of them to verify, so there may be one or two that don’t).

People not using DUB to manage their projects can potentially run into issues if they pull down DerelictUtil master and link it with a Derelict package that was compiled against DerelictUtil 1.0.x. If you are manually handling your project, or an IDE is without DUB, make sure to update and recompile all of your Derelict libraries with 2.0.0. Pay close attention to the dub/package.json of any Derelict-like bindings you use to see if any of them are using a == or ~> dependency on a 1.0.x version. If so, file an issue at that binding’s project page and ask them to update their dependency to 2.0.0.

Support for SDL 2.0.4 in Derelict

Thanks to Ben Boeckel, DerelictSDL2 now has support for SDL 2.0.4. It’s available in version tag 1.9.5, so you’ll want to specify that in your DUB configuration. Since SDL 2.0.4 hasn’t actually been released yet, Derelict still attempts to load SDL 2.0.2/3 by default. If you want are interested in using SDL 2.0.4 with Derelict, you’ll need to specify it with a SharedLibVersion when you call the load method.

DerelictSDL2.load(SharedLibVersion(2,0,4));

Migration Complete

I ditched my LEMP stack and set up a LAMP stack instead. I moved everything over to a cheaper VPS plan in the process. I was only using a tiny fraction of the resources I was paying for on the old plan. Anyway, I’m on more familiar ground now.

I was unable to do everything all at once, so it took longer than I anticipated because of interruptions (the biggest one being sleep). I’ve still got a couple of plugins to install and configure. But all of the critical stuff is done, as far as I can see. If you notice any issues, please let me know.

Oh, and I’ve got email notifications working this time around. I was never able to get it functioning on the other system. So if you do leave a comment, it shouldn’t languish for days without a response.

Blog Downtime and Derelict Updates

If you’ve dropped by here any time and gotten a “502 Bad Gateway” error, my inexperience at managing a LEMP stack is probably to blame. As soon as I can make the time for it, I’m going to move to something I’m much more familiar with and eliminate the problem once and for all. Time is something in short supply right now, but I really need to get this done as it’s annoying the hell out of me.

My time shortage also means I’m going to be slower than usual in responding to Derelict issues. I generally prefer to handle them as soon as I see them in my inbox if I can. Right now, I’m knee deep in a new project that’s going to require most of my free time for the next few months. I intend to make time for Derelict every weekend (and whenever I can find breathing room during the week), so please keep that in mind if you report any new issues. Pull requests are greatly appreciated and are guaranteed to get pulled immediately if I have no objections to them, but anything that requires more than a few minutes for me to fix is most likely going to be near the bottom of my priorities.

Preparing For DerelictSDL2 2.0

SDL 2.0.4 appears to be in the final push for release. Once it is out, I intend to update the SDL-2.0.x branch of DerelictSDL2 (where I’ve tagged the 1.9 series so far) and tag a 2.0 release. From that point forward, I will no longer be maintaining the other branches (corresponding to tags 1.0.x, 1.1.x, and 1.2.x).

Toward that end, I’d really like to strongly recommend anyone using DerelictSDL2 start using the 1.9 series today and, more importantly, let me know how you are getting on with it — especially if it’s working for you. There are effectively three API versions of SDL 2 right now: 2.0.0, 2.0.1 and 2.0.2/3 (2.0.3 was a bugfix release and has no API differences over 2.0.2). If you are require any of those as a minimum, then you can load it with the 1.9 series as described in the post where I introduced the SharedLibVersion feature, e.g.:

import derelict.sdl2.sdl;
void main() {
    // Require 2.0.0 as a minimum so that all SDL2 releases
    // can be loaded successfully.
    DerelictSDL2.load( SharedLibVersion( 2, 0, 0 ));
}

I also strongly recommend that you pass in 2.0.0 as above, allowing any SDL version to load, unless you absolutely require API functions from a later version. Particularly if you are distributing on Linux or one of the BSDs, which usually means relying on the SDL libraries being installed on the system. On Windows, where it’s customary to ship DLLs with the app, it’s not so important.

So, please, change your dub dependency to >=1.9.0 and let me know how it works out for you. If there are any problems, I’d really like to hear about them before I tag a 2.0 release.

Thanks!

DerelictAllegro5

I had a binding to Allegro 5 in an older iteration of Derelict, but it was problematic. There were unexpected crashes when using some Allegro dlls on Windows and there was a big issue with how to handle Allegro on Mac (it requires a special main function to run). So a while back I learned from reading about SeigeLord’s DAllegro5 that the crash issues were specific to dlls compiled with MinGW and have disappeared with newer versions of the compiler. I also discovered that he had come up with a way to deal with Mac. With those issues gone, I decided to start on a new DerelictAllegro5 binding for DerelictOrg. I worked on it sporadically, then somehow forgot all about it.

Recently, it popped back into my head so I dug up the source that I last touched in March of last year. To my surprise, I had managed to finish every module I had intended to finish. It only required a bit of tweaking to get my little allegtest app to compile and run. I’ve done a bit more work on it to make my life easier in maintaining it and now I think it’s ready for a work out, so I’ve pushed it to GitHub and will register derelict-allegro5 version 0.0.1 with dub as soon as I publish this post (I want to link here from the README until I get some better documentation).

If you are using or thinking about using Allegro 5, I’d appreciate if you’d test this out for me. Right now, it binds to the 5.0 series rather than the wip 5.1. There are a couple of things that make this binding different than other packages in Derelict and you need to be aware of them before using it.

First up, on Mac you need to launch the app with a special function in the loader. Allegro requires some special handling on OSX in order for things to work properly. I’ve adapted SeigeLord’s solution and created a function in the loader called “run”. It takes a pointer to a function that returns int and has no parameters. It will launch a separate thread and call the function pointer. So on OSX your app should call DerelictAllegro5.run(&foo) after you’ve loaded the libraries.

I’ve put up a sample at DPaste that shows how to load all of the Allegro libraries and handle the Mac workaround. Note that although the sample versions out the Mac stuff, you don’t need to do that if you don’t want. You can call the run method on any platform and it will work just fine. It’s up to you how to handle it. Also note that I’m catching any thrown Throwable in macMain, saving it in a module-scope variable, then rethrowing it in the main function. That’s because the function pointer passed to DerelictAllegro5.run will ultimately be called from the C side, so I want to make sure no exceptions are lost across the C/D boundary. If someone discovers that exceptions can cross that boundary on Mac without problem, then that isn’t necessary.

Second, the naming convention of the Allegro dlls on Windows is just outright annoying. Most C libraries out there do not include patch versions in the dll names, but all of the Allegro dlls do so. That means Derelict has to specifically ask for the 5.0.10 version of the libraries or the 5.0.11 version of the libraries and so on. On top of that, the dlls are compiled to either statically link with system libraries or not. If there’s an ‘-mt’ in the name, it’s the former, while ‘-md’ means the latter. Then there’s the option to use a monolithic dll which bundles all of the separate addons into one monster library. That’s not including the debug versions!

So, I had to make a choice: support every variation of the libraries or only rely on a specific set? I opted for the latter. By default, the loader for the core library and each addon expects the -mt versions of each library. Each loader will first look for the monolithic dll; next it will try 5.0.11; finally it will attempt to load 5.0.10. If you prefer to use the -md versions, or would like to support any 5.0.x version of the library, for now I recommend you just rename your dlls to something simple (like allegro5.dll, allegro5-audio.dll or whatnot) and pass those names to the load method for each loader to override the default behavior.

I have no idea if the Allegro5 build system is set up to build and install monolithic versions of the library on Mac and Linux, so the loaders currently don’t attempt to load those. However, the situation is better there with the 5.0.x versioning scheme, since most systems will probably be configured with a Mac framework or a dylib/so with the generic 5.0 prefix. This will allow any 5.0.x version to be loaded, though the loaders do look for 5.0.11 first on Linux (it’s intended to be the last release of the 5.0.x series, anyway). If any Allegro users on Mac or Linux could let me know about what exactly is installed on your system, that would be great. I’m particularly interested in whether or not there’s a monolithic version of the library available. Next time I boot into my Linux partition, I’ll see about installing Allegro and check it out myself (but I’m in no hurry to do that).

It seems like I’m missing something, but I can’t remember what it is. So that’s all for now. If you try DerelictAllegro5, please let me know even if it works flawlessly. Prebuilt Windows binaries for 5.0.10 are available from the Allegro Wiki. Linux users should be able to get 5.0.10 from your package manager. I’ve heard that SeigeLord updated MacPorts with 5.0.11. If you want to build it yourself, source packages for the recently released 5.0.11 and older versions are up at Sourceforge.