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