Closed chewi closed 2 years ago
Hmm… I haven't been able to find a copy of the SDL 1.2 based Dynamite Jack lying around. All the recent versions (from Steam and Humble) are SDL2-based, and work fine here.
Ah okay, I'll update the Gentoo package for it. Maybe there's still an issue to be fixed here, but could be tricky without the source.
Maybe there's still an issue to be fixed here, but could be tricky without the source.
That it works with real SDL1.2 mean that there is an issue to be fixed. Don't have access to that game myself, though.
Does anyone have this game and had a chance to investigate this issue? @icculus, @slouken?
I could send someone my copy if they can convince me they legally own it.
I could send someone my copy if they can convince me they legally own it.
It's Dynamite Jack, not Dynamic Jack, right? I own it, you can find it in my list of Steam games:
D'oh! Can't believe I didn't spot that.
And yes, I have no doubt you own it, Ryan! I'll mail you the binaries.
Binaries obtained, will look into this soon!
This is an issue with OpenGL scaling; if I turn it off, this gets past the title screen. Looking into it.
So what's happening is that Dynamic Jack links directly against libGL.so.1, and calls glXGetProcAddressARB() to look up GL entry points it needs, including glBindFramebufferEXT().
Later, it binds an FBO to use as a render target of some sort, and then binds FBO 0 when done, but our logical scaling code doesn't catch this so the game is rendering correctly to the backbuffer and then gets overwritten by the original frame that's sitting in our scaling FBO right before we swapbuffers.
The solution is to catch the call to glXGetProcAddressARB and slide our shims in, but I'm not sure how to force it to do so in a reasonable way, since the binary links directly to it in libGL.so.1. Would we have to resort to LD_PRELOAD?
Also assuming this will fail outright on Wayland, scaling or not.
Note that the Steam version is migrated to SDL2 and may or may not have solved these problems already.
For the old SDL 1.2 binary, I'd just say force OpenGL scaling off with the environment variable and call it a day, unless anyone has a good idea here?
No, that sounds like a reasonable resolution to me.
Fwiw, adding this to sdl12-compat fixes Dynamic Jack with OpenGL scaling without using LD_PRELOAD:
DECLSPEC void * SDLCALL glXGetProcAddressARB(const char *sym) { return SDL_GL_GetProcAddress(sym); }
(this isn't the exact function signature of the real glXGetProcAddressARB, but close enough.)
But this feels hella risky in case we get into an infinite loop where we eventually try to call the real glXGetProcAddressARB inside SDL2 but end up back here. I don't know if this was merely working by the grace of the dynamic linker in this instance, but in this case it did manage to route their function lookups through our stuff so we could override the proper framebuffer object entry points.
(or the dynamic linker could choose the real glXGetProcAddressARB over ours, too, I dunno.)
Could you guard against the loop with a static variable? Still not great though, so probably not worth it. It really depends how likely it is that other games do this. I'm getting the impression that this is a very isolated case.
Fwiw, adding this to sdl12-compat fixes Dynamic Jack with OpenGL scaling without using LD_PRELOAD:
DECLSPEC void * SDLCALL glXGetProcAddressARB(const char *sym) { return SDL_GL_GetProcAddress(sym); }
I think that is a bad idea..
I'm honestly surprised it worked here, but it makes sense when you think about it: SDL2 doesn't link against libGL, it looks up this function from a specific library it dlopen'd, so we aren't at the mercy of the dynamic linker there...but this still feels like too much of a gamble to commit.
One more followup on this: the SDL2 version of this game does not call glXGetProcAddress() directly. It's statically linked to SDL 2.0.8, but with a 32-bit build of SDL2 that has Wayland support, we can probably get this running natively on Wayland with the SDL_DYNAMIC_API environment variable.
Tried a few things to no avail. Original SDL1 works fine.