No X11 input events in DGA2 mode
Andy MacLean
andy-wine1 at themacleans.org.uk
Mon Jul 8 20:08:22 CDT 2002
I was trying to run Starcraft under wine in using the X11 DGA2 mode to
get a decent frame rate. I tried running it under various versions of
wine and got the same result every time. The problem is that when wine
runs the game using DGA2 it ignores all input from the keyboard and
mouse and so appears to hang. When running the game with DGA2 support
disabled (i.e. not running as root) everything works fine but I get a
much lower frame rate. I'm new to wine but I had a stab at fixing the
problem which as far as I can see is the following:
-> wine creates one X11 display connection for each thread and one
'global' display connection to use for various things like DGA2 which it
puts in the 'gdi_display' global variable. The thread specific
connections get put in x11drv_thread_data structure pointed to by the
driver_data pointer in each thread's thread specific structure.
-> wine then switches to DGA2 mode if it can and does an 'XSelectInput'
to turn on DGA2 input events. It switches to DGA2 mode using the
gdi_display connection so all input events will now come through this
connection.
-> at some point something asks for new X11 events. It goes into the
'X11DRV_MsgWaitForMultipleObjectsEx' function to poll the X11 display
connections for each thread. This ends up calling the 'process_events'
function in dlls/x11drv/event.c with the 'x11drv_thread_data' structure
for each thread. This is the only function that calls
'process_events', which is the only place that calls any X11 event
fetching function outside of 'wineclipserv.c' and 'clipping.c' (which
seem do something irrelevant to the dga2 problem).
-> but process_events can only look at the thread specific X11 display
connections since this is the data it gets passed. I cannot find any
code which sets up an 'x11drv_thread_data' structure for gdi_display and
XNextEvent is only ever called from inside process_events on
data->display. Therefore we never poll gdi_display for X11 events at
all so I never get any input. I tested this with some debug output code
and wine deffinitely never polls gdi_display for events at any time
while running the game. X11DRV_MsgWaitForMultipleObjectsEx explicitly
does an XFlush on gdi_display as though it is expecting to have to poll
it separately, but it never does ...
I tried changing 'process_events' in dlls/x11drv/events.c to the following:
static int process_events( struct x11drv_thread_data *data )
{
XEvent event;
int count = 0;
wine_tsx11_lock();
while ( XPending( data->display ) )
{
XNextEvent( data->display, &event );
wine_tsx11_unlock();
EVENT_ProcessEvent( &event );
count++;
wine_tsx11_lock();
}
#ifdef FIX_DGA2_INPUT
while ( DGAUsed && gdi_display != NULL && data->display !=
gdi_display &&
XPending( gdi_display ) )
{
XNextEvent( gdi_display, &event );
wine_tsx11_unlock();
EVENT_ProcessEvent( &event );
count++;
wine_tsx11_lock();
}
#endif
wine_tsx11_unlock();
return count;
}
And this fixed the problem. What's bugging me though is that if this is
the correct answer then how do any programs work at all in DGA2 mode?
Wouldn't any program hang in the same way as soon as wine switched to
DGA2 mode?
It would be handy if this were fixed in the wine code so I don't have to
keep downloading source and patching so can someone who knows more about
the code please let me know if they think this is worth submitting as a
patch or point me in the right direction if this is on the wrong track?
Thanks in advance,
A.
More information about the wine-devel
mailing list