opengl rendering to the wrong window

Lionel Ulmer lionel.ulmer at
Sat May 18 07:26:03 CDT 2002

> 	What could be causing it to be rendered in the wrong window?  The render 
> window has a hwnd =1003e and a drawable client/whole = 0x4000064/0x4000063 
> and the first couple of time through wglMakeCurrent the drawable that comes 
> back from the hdc that is passed (requested from 1003e) is 0x4000064 which 
> seems right, but I think this is some sort of test renderings offscreen 
> before the application comes up. Later in the logs this is not true.  GetDCEx 
> is called with 1003e, but it returns a hdc that has a different drawable 
> associated with it (the one for the root window I think).  But even if I try 
> to for the drawable to 0x4000064 is does not render in to the correct window 
> (it does not render at all).

Well, I spent some time looking at the problem and it is, as far as I know,
not a 'pure' OpenGL problem but rather a bad interaction between the way
Wine does its window management using X11 window and how GLX works. As far
as I know, this problem will be *very* difficult to solve (or the only way I
could see to solve it would lead to a major slow-down).

Anyway, let me tell what I found (so that people more knowledgeable than me
in Windows internals and how Wine emulates it can shredd it down :-) ) :

 - the first 'test drawings' are working fine using the 320x200 window as
   the window is not actually mapped on the screen yet => Wine uses the
   drawable from this window.

 - once the windows are actually on the screen and that the application
   tries to do a GetDC on the 0x1003e window (the one that I suppose is the
   320x200 drawing window), the shit hits the fan : if you look at the code
   in X11DRV_GetDC, you will see that if a window is visible (and has its
   parents visible too), and if none of its parents have the CLIPSIBLINGS
   flag on, the drawable associated to this DC is *not* the one of the
   target window, but the one of its parent (yeah, seems strange, but
   apparently in Windows, the default behaviour is to be able to erase your
   siblings when drawing) => we have the 520 x 200 window instead of the 320
   x 200 one when doing OpenGL.

   Now one would say 'yeah, but then how are what is displayed in this DC
   actually displayed on the screen' ? It's easy, it's done via the
   'IncludeInferiors' GraphicContext flag that tells X11 to not clip the
   drawings in this window by any child windows (and also actually by
   changing the 'org' coordinates of this DC).

   So the *big* problem is that GLX does not have the equivalent of this
   'includeInferiors' flag (ie any OpenGL drawings *are* clipped by the
   child windows of the window bound to the current context as there is no
   notion of GraphicContext associated to this binding).

Anyway, all this comes from the fact that the programmers were lazy and did
not add the 'DCX_CLIPSIBLINGS' flag to their GetDCEx call (I know it's not
needed because the clipping is done by OpenGL in the viewport call).

So the only viable solution I could see (ie viable in the sense that it
would work in all cases) would be to have all OpenGL drawings be 'indirect'
in a GLXPixmap whatever the case and use standard Wine (via X11) operations
to 'blit' it on screen. It would, of course, only work on double buffered
contexts and absolutely kill performance in any other cases.

Another possible solutions would be to have Wine hide all child window of
the one the context is bound to and add to the viewport call the DC's org
coordinates. That would fix the problem here, but would maybe have other
problems later on (as I do not know enough about Windows / Wine internals to
know if this could be problematic or not).

I will try to investigate the latter solution, but if anyone has other
ideas, feel free to raise hands :-)


		 Lionel Ulmer -

More information about the wine-devel mailing list