Discussion:
[Xcb] XCB/GLX and resizing windows leads to incorrectly places GLX contents
Ruben Van Boxem
2018-07-14 18:45:56 UTC
Permalink
Hello list,

I have set up a limited drawing and windowing framework and am able to draw
into a window using Skia by just blitting the produced image to screen
using xcb_put_image.
My event loop is set up to draw on Expose events, and I retrieve the actual
window geometry from xcb before drawing.

If I exchange this to OpenGL, and let Skia draw directly on screen, I get
into trouble when resizing my window.
The best I can do to describe this behaviour is that it seems as if the GL
content is not drawn at the correct position. If I remember correctly, a
similar effect ("accelerated" offset positions for window content) happened
if I would redraw on a ConfigureNotify event with the geometry of that
event.

It seems to resemble this bug:
https://bugs.freedesktop.org/show_bug.cgi?id=35945
Only difference is that I seem to be running on DRI3, and I do not get any
unknown events unless I set the environment variable
LIBGL_DRI3_DISABLE=true. Then the observed behaviour becomes much worse,
and I receive unknown events. I would guess that the workaround described
in the above bug report would work to fix that DRI2 issue.

Then remains the issue in DRI3 mode: I am not getting any unknown events
whatsoever, and can't find anything that would give me enough information
to actually fix this incorrect positioning of window content.

The relevant source code is here:
event handling:
https://github.com/skui-org/skui/blob/master/gui/events/xcb.c%2B%2B
xcb window (created through a connection from an Xlib Display for GLX):
https://github.com/skui-org/skui/blob/master/gui/native_window/xcb.c%2B%2B
glx setup:
https://github.com/skui-org/skui/blob/master/gui/native_visual/glx.c%2B%2B

The whole thing is quite a complicated setup as I want to handle several
types of windowing and graphics backends and this manner of split was the
natural result I came up with for now.
If you want to compile the code, you'll need 10-15 minutes, a recent C++
compiler and CMake. The executable in question is
"examples/widget_gallery/widget_gallery".

So to summarize: I see Bug 35945 and could probably handle that, but I also
see a less drastic but similar GLX/XCB problem when DRI3 is used in which
case the XESetEvent workaround will definitely not work. I do not see this
issue if I render to screen in pure xcb (no xlib/glx involved). I have no
idea what I can do to resolve this issue.
A movie of the effect is here:
DRI3:
https://www.dropbox.com/s/obkdzd2j67zl5yy/glx_context_resize_dri3.mp4?dl=0
DRI2:
https://www.dropbox.com/s/my8gg3rfcab45fg/glx_concext_resize_dri2.mp4?dl=0
XCB/CPU: https://www.dropbox.com/s/oxj06vbr8k6fvay/xcb_put_image.mp4?dl=0
The DRI2 movie is with LIBGL_DRI3_DISABLE=true, making the effect a lot
worse.

Thanks for any help!
Ruben Van Boxem
2018-07-14 18:55:17 UTC
Permalink
Post by Ruben Van Boxem
Hello list,
I have set up a limited drawing and windowing framework and am able to
draw into a window using Skia by just blitting the produced image to screen
using xcb_put_image.
My event loop is set up to draw on Expose events, and I retrieve the
actual window geometry from xcb before drawing.
If I exchange this to OpenGL, and let Skia draw directly on screen, I get
into trouble when resizing my window.
The best I can do to describe this behaviour is that it seems as if the GL
content is not drawn at the correct position. If I remember correctly, a
similar effect ("accelerated" offset positions for window content) happened
if I would redraw on a ConfigureNotify event with the geometry of that
event.
It seems to resemble this bug: https://bugs.freedesktop.org/
show_bug.cgi?id=35945
Only difference is that I seem to be running on DRI3, and I do not get any
unknown events unless I set the environment variable
LIBGL_DRI3_DISABLE=true. Then the observed behaviour becomes much worse,
and I receive unknown events. I would guess that the workaround described
in the above bug report would work to fix that DRI2 issue.
Then remains the issue in DRI3 mode: I am not getting any unknown events
whatsoever, and can't find anything that would give me enough information
to actually fix this incorrect positioning of window content.
event handling: https://github.com/skui-org/skui/blob/master/gui/events/
xcb.c%2B%2B
https://github.com/skui-org/skui/blob/master/gui/native_window/xcb.c%2B%2B
glx setup: https://github.com/skui-org/skui/blob/master/gui/native_
visual/glx.c%2B%2B
The whole thing is quite a complicated setup as I want to handle several
types of windowing and graphics backends and this manner of split was the
natural result I came up with for now.
If you want to compile the code, you'll need 10-15 minutes, a recent C++
compiler and CMake. The executable in question is "examples/widget_gallery/
widget_gallery".
So to summarize: I see Bug 35945 and could probably handle that, but I
also see a less drastic but similar GLX/XCB problem when DRI3 is used in
which case the XESetEvent workaround will definitely not work. I do not see
this issue if I render to screen in pure xcb (no xlib/glx involved). I have
no idea what I can do to resolve this issue.
DRI3: https://www.dropbox.com/s/obkdzd2j67zl5yy/glx_context_
resize_dri3.mp4?dl=0
DRI2: https://www.dropbox.com/s/my8gg3rfcab45fg/glx_concext_
resize_dri2.mp4?dl=0
XCB/CPU: https://www.dropbox.com/s/oxj06vbr8k6fvay/xcb_put_image.mp4?dl=0
The DRI2 movie is with LIBGL_DRI3_DISABLE=true, making the effect a lot
worse.
Thanks for any help!
Hi everyone,

sorry to be that guy who asks his question and immediately after sending it
to the world, finds a solution:
It appears that this sequence:
glXSwapBuffers(display, drawable);
glClear(GL_COLOR_BUFFER_BIT);

does not work and actually causes the issue I tried to describe in detail
in my previous email.
Removing the glClear makes the problem go away.

Unfortunately I'm not so experienced with OpenGL so I have no idea why this
actually causes/fixes the issue.

Ruben
Michel Dänzer
2018-07-20 10:54:18 UTC
Permalink
Post by Ruben Van Boxem
Post by Ruben Van Boxem
Hello list,
I have set up a limited drawing and windowing framework and am able to
draw into a window using Skia by just blitting the produced image to screen
using xcb_put_image.
My event loop is set up to draw on Expose events, and I retrieve the
actual window geometry from xcb before drawing.
If I exchange this to OpenGL, and let Skia draw directly on screen, I get
into trouble when resizing my window.
The best I can do to describe this behaviour is that it seems as if the GL
content is not drawn at the correct position. If I remember correctly, a
similar effect ("accelerated" offset positions for window content) happened
if I would redraw on a ConfigureNotify event with the geometry of that
event.
It seems to resemble this bug: https://bugs.freedesktop.org/
show_bug.cgi?id=35945
Only difference is that I seem to be running on DRI3, and I do not get any
unknown events unless I set the environment variable
LIBGL_DRI3_DISABLE=true. Then the observed behaviour becomes much worse,
and I receive unknown events. I would guess that the workaround described
in the above bug report would work to fix that DRI2 issue.
Then remains the issue in DRI3 mode: I am not getting any unknown events
whatsoever, and can't find anything that would give me enough information
to actually fix this incorrect positioning of window content.
event handling: https://github.com/skui-org/skui/blob/master/gui/events/
xcb.c%2B%2B
https://github.com/skui-org/skui/blob/master/gui/native_window/xcb.c%2B%2B
glx setup: https://github.com/skui-org/skui/blob/master/gui/native_
visual/glx.c%2B%2B
The whole thing is quite a complicated setup as I want to handle several
types of windowing and graphics backends and this manner of split was the
natural result I came up with for now.
If you want to compile the code, you'll need 10-15 minutes, a recent C++
compiler and CMake. The executable in question is "examples/widget_gallery/
widget_gallery".
So to summarize: I see Bug 35945 and could probably handle that, but I
also see a less drastic but similar GLX/XCB problem when DRI3 is used in
which case the XESetEvent workaround will definitely not work. I do not see
this issue if I render to screen in pure xcb (no xlib/glx involved). I have
no idea what I can do to resolve this issue.
DRI3: https://www.dropbox.com/s/obkdzd2j67zl5yy/glx_context_
resize_dri3.mp4?dl=0
DRI2: https://www.dropbox.com/s/my8gg3rfcab45fg/glx_concext_
resize_dri2.mp4?dl=0
XCB/CPU: https://www.dropbox.com/s/oxj06vbr8k6fvay/xcb_put_image.mp4?dl=0
The DRI2 movie is with LIBGL_DRI3_DISABLE=true, making the effect a lot
worse.
Thanks for any help!
Hi everyone,
sorry to be that guy who asks his question and immediately after sending it
glXSwapBuffers(display, drawable);
glClear(GL_COLOR_BUFFER_BIT);
does not work and actually causes the issue I tried to describe in detail
in my previous email.
Removing the glClear makes the problem go away.
When the window size has changed, do you call glViewport et al between
glXSwapBuffers and glClear?

Which version of Mesa are you testing with?
--
Earthling Michel Dänzer | http://www.amd.com
Libre software enthusiast | Mesa and X developer
Ruben Van Boxem
2018-07-20 17:34:39 UTC
Permalink
Post by Michel Dänzer
When the window size has changed, do you call glViewport et al between
glXSwapBuffers and glClear?
Which version of Mesa are you testing with?
Mesa version is 18.1.4.

I think I have fixed this along with probably some other mistakes on my end.
To summarize my current code (which solves the issues I described above):
- window::repaint(bool force): fetches current geometry through
xcb_get_geometry/xcb_query_tree/xcb_translate_coordinates and stores it,
calls glXMakeCurrent, glViewport with fetched geometry. Next, Skia draws
into the framebuffer with OpenGL, glXSwapBuffers is called after that. If
force = false, only actually do anything (glXMakeCurrent, glViewport, Skia
drawing, glXSwapBuffers) if geometry has changed, otherwise, continue on.
- on expose event: repaint(true)
- on configure event: repaint(false)
- on map event: repaint(true)
- For DRI2 (verified by setting LIBGL_DRI3_DISABLE=true): I handle all
unknown events with this piece of code:
auto proc = XESetWireToEvent(display.get(), event.response_type, 0);
if(proc)
{
XESetWireToEvent(display.get(), event.response_type, proc);
XEvent dummy;
event.sequence =
static_cast<std::uint16_t>(LastKnownRequestProcessed(display.get()));
proc(display.get(), &dummy, reinterpret_cast<xEvent*>(&event));
}

Previously, I did not repaint on configure notify events, which seems to
cause issues with composited GLX windows.
If I repaint(true) on configure, I get too many repaint events that still
cause repaints even after I've physically stopped resizing the window.
This gives me repaint when needed, and no funny business when resizing.
I'm probably missing some logic for scenarios I haven't considered yet but
this seems to cover most of it at least in an efficient manner.
The DRI2 issue actually was unrelated, but had an even more drastic effect
on repainting on resize which really needs the above fix to function
properly.
Oh, and this is all running in a window specific thread that hosts the
window-specific event loop, so I lock a mutex inside the repaint function
to prevent a closing window from invalidating the GLX context drawable.

So the glClear call actually only seemed to cause it (probably because it
exacerbated the effect). It was nonetheless unnecessary in my current setup.

Thanks and I hope this helps anyone looking for help in this area finds
this useful. I've been fighting to perfect this for quite some time and am
sure it still is far from optimal.

Ruben

Loading...