Closed sulix closed 2 years ago
Stack realignment: CivCTP's stacks are 4-byte aligned. Most distros are built with 16-byte aligned stacks to use SSE. Use attribute((force_align_arg_pointer)) to realign stacks in sdl12-compat to bridge this gap.
This is going to blow up calling into glibc, too, even if it doesn't have other external dependencies.
Does it really make that much sense to hack sdl12-compat to work with games that use SDL1.1 (not 1.2) and are generally incompatible with modern glibc etc?
I hate to say it, but maybe Wine is the better solution here
I don't think 1.1 had any API changes over 1.2. The hurdles to the Loki games are going to be larger than SDL, but these issues are all 1.2 issues as well, so far.
I'm trying to play Loki's port of Sid Meier's Alpha Centauri (aka smac) - it seems to be a bit less ancient than the Civ as its dynamic executable is linked against SDL1.2 at least.
But it still requires an old glibc of course... Thus I'm trying my luck with this bunch of old libraries - https://www.improbability.net/loki/ It actually seems to work here (or simply using the statically built executable works too).
But how one goes about using the compat shim with this pile of old libs? Just dropping the compiled .so in place of the libsdl1.2 provided by the above pack results in a "bad dynamic tag" from the linker... Would it be necessary to compile the shim with an equally old toolchain as well? How are you doing it?
Does anyone know what causes these incompatibilies?
I first thought this was about libc5 vs libc6, but apparently it's about glibc >= 2.3 vs <= 2.2.x (which should both be libc6 and compatible, right?)
urgh, https://bugzilla.redhat.com/show_bug.cgi?id=112707#c1 suggests that those old Loki binaries statically linked the dynamic linker (I think this is usually ld-linux.so
which is part of glibc? or maybe libdl.so
? or both?), which should only work with the glibc version it belonged to, and might work with other versions "just by luck" and apparently (in case of the version Loki statically linked) doesn't work at all with glibc versions >= 2.3.
I wonder if they also linked other parts of the glibc statically, and if that was intentional (in that case: WHY?!) or happened accidentally.
Either way, I guess that fixing this "properly" would probably require to binary-patch the original executables to not use those statically linked linker/libc functions anymore, which certainly sounds challenging.
I've not found glibc to be the main problem with the .dynamic
versions of the Loki executables: it's the libstdc++ stuff which causes more problems.
That being said, there's no way you're going to get sdl12-compat working with those "Loki compat libraries": you'd need to recompile everything (sdl12-compat, your system graphics drivers, etc) against them, which probably wouldn't work.
My strategy has been to run the game against your normal system libc, but patch out the few bits of libstdc++ which are broken:
perl -pe 's/__builtin_/x_builtin_/g' <smac.dynamic >smac.dynamic-fixed
LD_LIBRARY_PATH=. LD_PRELOAD=libcivctp_wrapper.so ./smac.dynamic-fixed
libsmpeg-0.4.so.0
available.)To then run in under sdl12-compat, you'll need to load it in, as well as libX11.so.6, as Alpha Centauri expects that SDL1.2 links that unconditionally:
LD_LIBRARY_PATH=.:~/Development/sdl12-compat/build32 LD_PRELOAD=libcivctp_wrapper.so:libX11.so.6 ./smac.dynamic-fixed
You can also use patchelf to add the library dependencies with:
patchelf --add-needed libcivctp_wrapper.so --add-needed libX11.so.6 --add-rpath "\$ORIGIN" smac.dynamic-fixed
That's enough to get SMAC to boot under sdl12-compat for me, though it's likely going to be a bit unstable (particularly if it does anything multithreaded with the rendering like civctp does.)
Thanks for a great peace of hack-fu.
Also seems to work without sticking libX11 in, linked in down the road as usual...
not too functional unfortunately (neither tho is the static compiled-in binary)
Multithreaded SDL_UpdateRects(): CivCTP calls SDL_UpdateRects() from two different threads, only one of which is the original thread. Under wayland (and nvidia+x11), this results in eglMakeCurrent failing in the renderer, and the texture locking/reupload failing a lot of the time (mouse cursor only visible sometimes, YUV overlays show up green, etc). It might be contributing to the random crashing in the renderer/Mesa on X11/Intel, too. Maybe we should keep a shadow surface in local memory (without needing to call into GL to lock it each call), and then defer the actual updates to present, which we can defer to the main thread? Though that might not work, as the "main" thread might not be doing any SDL calls at all during some parts of the game…
@sulix When you get a moment, can you see if the latest in revision control fixes this specific issue? I think it might.
Stack realignment: CivCTP's stacks are 4-byte aligned. Most distros are built with 16-byte aligned stacks to use SSE. Use attribute((force_align_arg_pointer)) to realign stacks in sdl12-compat to bridge this gap.
I don't mind adding this, but I can't coerce GCC to output different code, either with this attribute or -mstackrealign on the gcc command line, at least with a little test program.
This is the current patch. If it works for you, regardless of my test program, let's put it in revision control, or something like it.
CD audio / game audio device re-opening: The format conversion between the 22050/mono/8bit and 44100/stereo/16bit big-endian when mixing CD audio and SDL audio is broken if the (real) device is closed/re-opened to pick a better common format. Forcing sdl12-compat to always open the real device at 44100/stereo/16bit works around this, but there's clearly a real bug here.
While I'm just dumping stuff on @sulix here (sorry!), is this still broken? These should both be going through separate SDL_AudioStreams to convert as necessary, but maybe it wasn't at the time? I'll try to roll a simple reproduction case outside of Civ:CTP if this is still hosed for you.
For reopening the audio device, this patch makes loopwave.c play for 5 seconds, then open a CD and start playing it. It...sounds okay to me...?
Here's sample.wav converted to 22050/mono/8-bit:
sample-wav-22050-mono-8bit.zip
So I ran it like this (put any MP3 in the cdrom directory, named "track01.mp3")
SDL12COMPAT_FAKE_CDROM_PATH=/home/icculus/projects/sdl12-compat/cmake-build/cdrom SDL12COMPAT_DEBUG_LOGGING=1 LD_LIBRARY_PATH=. ./loopwave ~/Desktop/sample.wav
diff --git a/test/loopwave.c b/test/loopwave.c
index 414b9ed..ec6cfcf 100644
--- a/test/loopwave.c
+++ b/test/loopwave.c
@@ -64,9 +64,12 @@ int main(int argc, char *argv[])
{
char name[32];
const char *file;
+ int delays = 0;
+ SDL_CD *cdrom = NULL;
+ CDstatus status;
/* Load the SDL library */
- if ( SDL_Init(SDL_INIT_AUDIO) < 0 ) {
+ if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_CDROM) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
return(1);
}
@@ -100,12 +103,38 @@ int main(int argc, char *argv[])
/* Let the audio run */
printf("Using audio driver: %s\n", SDL_AudioDriverName(name, 32));
- while ( ! done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) )
+ while ( ! done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING) ) {
SDL_Delay(1000);
+ if (delays < 5) {
+ delays++;
+ } else if (delays == 5) {
+ if (SDL_CDNumDrives() == 0) {
+ printf("No CD drives detected, not trying to play a disc.\n");
+ } else if ((cdrom = SDL_CDOpen(0)) == NULL) {
+ printf("Failed to open CD drive 0: %s\n", SDL_GetError());
+ } else if ((status = SDL_CDStatus(cdrom)) == CD_ERROR) {
+ printf("Failed to get CD status: %s\n", SDL_GetError());
+ } else if (status == CD_TRAYEMPTY) {
+ printf("CD tray is empty, can't play a disc.\n");
+ } else if (SDL_CDPlayTracks(cdrom, 0, 0, 0, 0) == -1) {
+ printf("Failed to play tracks from CD drive 0: %s\n", SDL_GetError());
+ } else {
+ printf("Playing tracks from CD drive 0!\n");
+ }
+ delays++; /* make this not attempt CD work again. */
+ }
+ }
/* Clean up on signal */
SDL_CloseAudio();
SDL_FreeWAV(wave.sound);
+
+ if (cdrom) {
+ SDL_CDStop(cdrom);
+ SDL_CDClose(cdrom);
+ cdrom = NULL;
+ }
+
SDL_Quit();
return(0);
}
I'm thinking, though, whether this works now or not, it might be better to always open the audio device at CD-ROM quality if the app asks for less, so there's never a scenario where you have to close the audio device and reopen it to accommodate things. You just have to make sure the SDL_AudioStream manages conversion, which we already have to do anyhow.
This would eliminate the gap in audio you hear in that patched loopwave.c, where it has to dump the audio device after 5 seconds to handle CD playback, and also a FIXME that I handwaved away about what to do if the reopening fails and something that was working fine is now screwed.
I started testing this earlier today before getting hit by a few unrelated disasters.
tl;dr, it's still broken.
SDL_RENDER_DRIVER=software SDL_FRAMEBUFFER_ACCELERATION=false
fixes some of those issues, but make the screen terribly flickery, s though rendering directly to the frontbuffer.SDL_PumpEvents()
, so a proper event thread implementation is probably required.Alas, I'm going to be on planes and overseas for the next couple of weeks, so won't have too much time to look into this in more detail until I get back. I'll try to give this one more look tomorrow before I leave and upload any relevant stacktraces if I can, though…
CivCTP seems to render from multiple threads (even within the same frame), not just from a single background thread. For example, the mouse cursor seems to be rendered in a different thread from the game, leading to a black screen with mouse trails with the current implementation. SDL_RENDER_DRIVER=software SDL_FRAMEBUFFER_ACCELERATION=false fixes some of those issues, but make the screen terribly flickery, s though rendering directly to the frontbuffer.
So the latest tries to reset the GL context whenever we touch VideoRenderer20, which solves a lot of these problems, but I'm wondering if we should also wrap any access to VideoRenderer20 in a mutex, which might help if these threads are all competing for it.
In theory, dirty rectangles shouldn't move from the software surface to the renderer until it's time to present it on the screen, which should work with this scheme, but how sdl12-compat decides it's time to present is a whole different problem (doubly so if PumpEvents is going wild in (multiple?) other threads), and that might be the part we have to solve somehow, or perhaps wrap in the same mutex we wrap VideoRenderer20 in.
I think I'd tried hacking it to always open in CD quality, and that fixed it, but I'll have to look and see if I still have that hacky experimental branch lying around somewhere.
Just pushed changes to do this, so maybe it's fixed now? :)
Alas, I'm going to be on planes and overseas for the next couple of weeks
No worries, I'm going to bump this out of the milestone for now, and we can revisit it later.
Yup, the CD audio / sound stuff works now.
Stack realignment: CivCTP's stacks are 4-byte aligned. Most distros are built with 16-byte aligned stacks to use SSE. Use attribute((force_align_arg_pointer)) to realign stacks in sdl12-compat to bridge this gap.
I don't mind adding this, but I can't coerce GCC to output different code, either with this attribute or -mstackrealign on the gcc command line, at least with a little test program.
This is the current patch. If it works for you, regardless of my test program, let's put it in revision control, or something like it.
This patch does work for me: without it, CivCTP will crash on startup with a self-compiled SDL2 build, with it, it's fine (or, at least, only as broken as the distro-provided SDL2 build).
I can also see the fixups in the generated code (apart from these instructions at the start, the implementations are the same):
00004421 <SDL_SetModState>:
4421: 8d 4c 24 04 lea 0x4(%esp),%ecx
4425: 83 e4 f0 and $0xfffffff0,%esp
4428: ff 71 fc push -0x4(%ecx)
Pushed a thing to serialize access to the renderer, which maybe doesn't fix the remaining issue, but it's a start if we have two threads trying to present to the screen at the same time. I probably have to try to get a build of Call to Power running here next.
Okay, I got a running build of Civ:CTP running last night.
So this is a bit of a mess, I couldn't get the game to start because it couldn't open profile.txt
, and when I strace'd it, it was trying to open it in a directory called ctdata/englisish
instead of ctp_data/english
, so there's either a buffer the game initialized incorrectly or a C runtime string function that behaves differently in modern times, or something like that, and likely other places this happens elsewhere.
A symlink fixed this one, but it's pretty clear we're only going to run so far with this one from the 23-year-old binaries. It was built in a time where Valgrind/AddressSanitizer/static analysis didn't exist, and C++ tools were just less good in general, so I wouldn't be surprised if we end up at the mercy of the OS's memory manager here even with perfect SDL-1.2 compatibility.
Ok, so this patch gets Call to Power rendering.
I can see this potentially causing regressions, so we're probably going to need to hide at least this last bullet point behind the quirks mechanism, if not all of them...but this patch does get the game to render correctly with sdl12-compat.
Also, the game is setting a 1920x1080 (my laptop's desktop resolution) video mode, and then centering the game in it. Forcing SDL_GetVideoInfo() to report something smaller didn't help, but I didn't investigate further, and the game could benefit from scaling, even if we need a quirk to force this, too. Something to consider.
It also reliably crashes (in the game, not in sdl12-compat) within three moves with a dereferenced NULL pointer, but that's probably beyond my control.
diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 6ec6fb9..29825fc 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -1023,6 +1023,9 @@ static EventQueueType EventQueuePool[SDL12_MAXEVENTS];
static EventQueueType *EventQueueHead = NULL;
static EventQueueType *EventQueueTail = NULL;
static EventQueueType *EventQueueAvailable = NULL;
+static unsigned long SetVideoModeThread = 0;
+static SDL_bool VideoSurfaceUpdatedInBackgroundThread = SDL_FALSE;
+
/* This is a KEYDOWN event which is being held for a follow-up TEXTINPUT */
static SDL12_Event PendingKeydownEvent;
@@ -5295,6 +5298,9 @@ EndVidModeCreate(void)
QueuedDisplayOverlays.next = NULL;
QueuedDisplayOverlaysTail = &QueuedDisplayOverlays;
+ VideoSurfaceUpdatedInBackgroundThread = SDL_FALSE;
+ SetVideoModeThread = 0;
+
return NULL;
}
@@ -6048,6 +6054,11 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
}
}
+ SetVideoModeThread = SDL20_ThreadID();
+ VideoSurfacePresentTicks = 0;
+ VideoSurfaceLastPresentTicks = 0;
+ VideoSurfaceUpdatedInBackgroundThread = SDL_FALSE;
+
SDL20_RaiseWindow(VideoWindow20);
/* SDL 1.2 always grabbed input if the video mode was fullscreen. */
@@ -6055,9 +6066,6 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags12)
HandleInputGrab(SDL12_GRAB_ON);
}
- VideoSurfacePresentTicks = 0;
- VideoSurfaceLastPresentTicks = 0;
-
if ((flags12 & SDL12_OPENGL) == 0) {
/* see notes above these functions about GL context resetting. Force a lock/unlock here to set that up. */
LockVideoRenderer();
@@ -6377,6 +6385,7 @@ PresentScreen(void)
}
SDL20_RenderPresent(renderer);
+ VideoSurfaceUpdatedInBackgroundThread = SDL_FALSE;
VideoSurfaceLastPresentTicks = SDL20_GetTicks();
VideoSurfacePresentTicks = 0;
@@ -6539,6 +6548,8 @@ SDL_GL_Unlock(void)
DECLSPEC12 void SDLCALL
SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
{
+ const SDL_bool ThisIsSetVideoModeThread = (SDL20_ThreadID() == SetVideoModeThread);
+
/* strangely, SDL 1.2 doesn't check if surface12 is NULL before touching it */
/* (UpdateRect, singular, does...) */
@@ -6558,6 +6569,7 @@ SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
* but in practice most apps never got a double-buffered surface and
* don't handle it correctly, so we have to work around it. */
if (surface12 == VideoSurface12) {
+ const SDL_bool upload_later = !ThisIsSetVideoModeThread;
SDL_Palette *logicalPal = surface12->surface20->format->palette;
const int pixsize = surface12->format->BytesPerPixel;
const int srcpitch = surface12->pitch;
@@ -6569,7 +6581,10 @@ SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
for (i = 0; i < numrects; i++) {
UpdateRect12to20(surface12, &rects12[i], &rect20, &whole_screen);
- if (!rect20.w || !rect20.h) {
+
+ if (upload_later) {
+ continue;
+ } else if (!rect20.w || !rect20.h) {
continue;
} else if (SDL20_LockTexture(VideoTexture20, &rect20, &pixels, &pitch) < 0) {
continue; /* oh well */
@@ -6608,7 +6623,10 @@ SDL_UpdateRects(SDL12_Surface *surface12, int numrects, SDL12_Rect *rects12)
VideoConvertSurface20->h = VideoSurface12->h;
}
- if (whole_screen) {
+ if (upload_later) {
+ VideoSurfaceUpdatedInBackgroundThread = SDL_TRUE;
+ VideoSurfacePresentTicks = whole_screen ? 1 : VideoSurfaceLastPresentTicks + GetDesiredMillisecondsPerFrame(); /* flip it later (or as soon as the main thread can). */
+ } else if (whole_screen) {
PresentScreen(); /* flip it now. */
} else {
VideoSurfacePresentTicks = VideoSurfaceLastPresentTicks + GetDesiredMillisecondsPerFrame(); /* flip it later. */
@@ -6661,14 +6679,24 @@ HandleKeyRepeat(void)
DECLSPEC12 void SDLCALL
SDL_PumpEvents(void)
{
+ const SDL_bool ThisIsSetVideoModeThread = (SDL20_ThreadID() == SetVideoModeThread);
SDL_Event e;
+ if (!ThisIsSetVideoModeThread) {
+ return;
+ }
+
/* If the app is doing dirty rectangles, we set a flag and present the
* screen surface when they pump for new events if we're close to 60Hz,
* which we consider a sign that they are done rendering for the current
* frame and it would make sense to send it to the screen. */
+
if (VideoSurfacePresentTicks && SDL_TICKS_PASSED(SDL20_GetTicks(), VideoSurfacePresentTicks)) {
- PresentScreen();
+ if (VideoSurfaceUpdatedInBackgroundThread) {
+ SDL_Flip(VideoSurface12); /* this will update the texture and present. */
+ } else {
+ PresentScreen();
+ }
}
if (EventQueueMutex) {
@@ -7618,6 +7646,18 @@ SDL_SetTimer(Uint32 interval, SDL12_TimerCallback callback)
return 0;
}
+DECLSPEC12 void SDLCALL
+SDL_Delay(Uint32 ticks)
+{
+ /* In case there's a loading screen from a background thread and the main thread is waiting... */
+ const SDL_bool ThisIsSetVideoModeThread = (SDL20_ThreadID() == SetVideoModeThread);
+ if (ThisIsSetVideoModeThread && VideoSurfaceUpdatedInBackgroundThread) {
+ SDL_Flip(VideoSurface12); /* this will update the texture and present. */
+ }
+ SDL20_Delay(ticks);
+}
+
+
DECLSPEC12 int SDLCALL
SDL_putenv(const char *_var)
{
diff --git a/src/SDL20_syms.h b/src/SDL20_syms.h
index df76bfa..e5469b8 100644
--- a/src/SDL20_syms.h
+++ b/src/SDL20_syms.h
@@ -232,7 +232,7 @@ SDL20_SYM_PASSTHROUGH(SDL_bool,HasAltiVec,(void),(),return)
SDL20_SYM(SDL_TimerID,AddTimer,(Uint32 a, SDL_TimerCallback b, void *c),(a,b,c),return)
SDL20_SYM(SDL_bool,RemoveTimer,(SDL_TimerID a),(a),return)
SDL20_SYM_PASSTHROUGH(Uint32,GetTicks,(void),(),return)
-SDL20_SYM_PASSTHROUGH(void,Delay,(Uint32 a),(a),)
+SDL20_SYM(void,Delay,(Uint32 a),(a),)
SDL20_SYM(SDL_bool,IsGameController,(int a),(a),return)
SDL20_SYM(const char *,GameControllerNameForIndex,(int a),(a),return)
Okay, I got a running build of Civ:CTP running last night.
So this is a bit of a mess, I couldn't get the game to start because it couldn't open
profile.txt
, and when I strace'd it, it was trying to open it in a directory calledctdata/englisish
instead ofctp_data/english
, so there's either a buffer the game initialized incorrectly or a C runtime string function that behaves differently in modern times, or something like that, and likely other places this happens elsewhere.A symlink fixed this one, but it's pretty clear we're only going to run so far with this one from the 23-year-old binaries. It was built in a time where Valgrind/AddressSanitizer/static analysis didn't exist, and C++ tools were just less good in general, so I wouldn't be surprised if we end up at the mercy of the OS's memory manager here even with perfect SDL-1.2 compatibility.
I'm still away (back next week), but IIRC, this was due to the CivCTP relying on the C string functions working with overlapping strings, hence the hacks here: https://gist.github.com/sulix/09f059c468fcb58eefbca8ef46006ccb#file-civctp_wrapper-c-L50
Didn't have time to test it in detail, but running with this patch (and my libcivctp_wrapper.so) was playable for quite a while under X11, but deadlocked pretty quickly under wayland.
It also had some flickering background for the wonder videos, and deadlocked afterwards.
Still, this is working much better than I expected!
Also, the game is setting a 1920x1080 (my laptop's desktop resolution) video mode, and then centering the game in it. Forcing SDL_GetVideoInfo() to report something smaller didn't help, but I didn't investigate further, and the game could benefit from scaling, even if we need a quirk to force this, too. Something to consider.
It gets this value from SDL_ListModes(), presumably (although it doesn't call that with SDL_FULLSCREEN, so it returns -1, so beats me), but setting this in the userprofile.txt lets you dictate a fullscreen resolution.
TryWindowsResolution=No
ScreenResWidth=1024
ScreenResHeight=768
fullscreen=Yes
640x480 seems to be the "native" resolution of the game, at least for menus and the intro video.
...but before I realized any of this, I added 40dff443364acf998c6cc0d9d45f3a152aba9b05 to let sdl12-compat clamp max reported resolution, which is still useful if we find a game that wants to find the largest resolution, and just wasn't prepared for a world that has retina displays.
this was due to the CivCTP relying on the C string functions working with overlapping strings, hence the hacks here:
Ah, I had this library, and patched the __builtin things, but forgot to patch the string functions! It runs much better now.
I don't know enough about this game to say that it always decides to render its mpeg videos unscaled and centered, but a quirk that says "scale all YUV video to the full resolution" might be useful for this game.
But also, this feels like meddling, a little bit.
Okay, I put that multithreaded wrangling patch behind a quirk and pushed it, which I think resolves the last pending thing with Civ:CTP.
If there are no objections, I'll close this bug.
FYI: I finally got around to writing up a guide on how to get this working, including how to patch the game's recursive mutex implementation (which seems to rely on LinuxThreads).
See: https://davidgow.net/hacks/civctp.html
With all of the patches listed there, the game seems to work perfectly on my system with the latest sdl12-compat.
Should we put that link in COMPATIBILITY.md?
Should we put that link in COMPATIBILITY.md?
Most of the issues are more general "this is ancient" than sdl12-compat specific, but nevertheless I've sent out PR #291 as some shameless self-promotion for my website. :-)
[Just dropping my notes about this here: I may split things up and/or fix them if I get some time…]
There are a large number of issues with Civilization: Call to Power v1.2a (it being an ancient SDL 1.1 game with a bunch of glibc/libstdc++ incompatibilities). Getting it to run even with real SDL 1.2 on a modern system (i.e., with modern glibc, etc, dynamically linked) is a chore, involving a lot of hex editing and patching. See: https://gist.github.com/sulix/09f059c468fcb58eefbca8ef46006ccb
That being said, while it does crash occasionally regardless, it does work considerably better with the real SDL 1.2 than with sdl12-compat. Maybe some of the issues could affect other games as well:
SDL_INIT_EVENTTHREAD
: CivCTP uses this, and doesn't often callSDL_PumpEvents()
otherwise. Hacked around by callingSDL_PumpEvents()
from withinSDL_PeepEvents()
. There may need to be more work on it to fix the next issue, though…SDL_UpdateRects()
: CivCTP callsSDL_UpdateRects()
from two different threads, only one of which is the original thread. Under wayland (and nvidia+x11), this results in eglMakeCurrent failing in the renderer, and the texture locking/reupload failing a lot of the time (mouse cursor only visible sometimes, YUV overlays show up green, etc). It might be contributing to the random crashing in the renderer/Mesa on X11/Intel, too. Maybe we should keep a shadow surface in local memory (without needing to call into GL to lock it each call), and then defer the actual updates to present, which we can defer to the main thread? Though that might not work, as the "main" thread might not be doing any SDL calls at all during some parts of the game…__attribute__((force_align_arg_pointer))
to realign stacks in sdl12-compat to bridge this gap.SDL_FreeYUVOverlay()
should resetQueuedDisplayOverlay12 = NULL;
: I don't think this is the cause of any of the issues, but seems like it's a real bug.XNextEvent
,XSync
,XGetWindowAttributes
,XFree
,XInternAtom
,XSendEvent
andXQueryPointer
. This doesn't seem to cause any issues, though, even under Wayland?