opengl rendering to the wrong window
lionel.ulmer at free.fr
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 - http://www.bbrox.org/
More information about the wine-devel