I created the attached patch, based on an upstream patch. I re-compiled the Wine packages with this patch, and tested it. It prevents Flight Simulator 2004 and Age of Empires II from crashing.
In AoE, the game is playable, though in my case the window contents wasn't correctly sized to the (Wine desktop) window size; this might be specific to my current set-up though, and I could do more testing. In FS, the menu is usable, but when flying, the screen contents is garbage, and the 3D elements (environment and also cockpit elements) are not drawn. The window menu *is* visible. The game is not crashed though, and based on the sounds, it does respond as expected to keyboard input. Note: I used a VM with i386 Debian 11 installed to compile the i386 Wine packages. Getting the wine packages compiled took a lot more effort than creating the patch for this Wine version.
From: Corné Plooy <cornware...@ultimatestunts.nl> Subject: [PATCH] x11drv: Remove active client window from window data before deleting it. Fixes a crash with BadDrawable X error which happens when client window is used in windows.c:sync_client_position() after the GL drawable has been deleted. This does not happen under normal circumstances as the next GL drawable created overrides client window in window structure. But in case new drawable gets DC_GL_PIXMAP_WIN type it doesn't. Origin: https://bugs.winehq.org/attachment.cgi?id=67883 Bug: https://bugs.winehq.org/show_bug.cgi?id=49649 Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1002023 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -241,6 +241,7 @@ struct gl_drawable { LONG ref; /* reference count */ + HWND hwnd; enum dc_gl_type type; /* type of GL surface */ GLXDrawable drawable; /* drawable for rendering with GL */ Window window; /* window if drawable is a GLXWindow */ @@ -1162,10 +1163,23 @@ { case DC_GL_WINDOW: case DC_GL_CHILD_WIN: + { + struct x11drv_win_data *data = get_win_data( gl->hwnd ); + TRACE( "destroying %lx drawable %lx\n", gl->window, gl->drawable ); + if (data) + { + if (data->client_window == gl->window) + { + XDeleteContext( data->display, data->client_window, winContext ); + data->client_window = 0; + } + release_win_data( data ); + } pglXDestroyWindow( gdi_display, gl->drawable ); XDestroyWindow( gdi_display, gl->window ); break; + } case DC_GL_PIXMAP_WIN: TRACE( "destroying pixmap %lx drawable %lx\n", gl->pixmap, gl->drawable ); pglXDestroyPixmap( gdi_display, gl->drawable ); @@ -1321,6 +1335,7 @@ /* Default GLX and WGL swap interval is 1, but in case of glXSwapIntervalSGI * there is no way to query it, so we have to store it here. */ + gl->hwnd = hwnd; gl->swap_interval = 1; gl->refresh_swap_interval = TRUE; gl->format = format;