Jump to content
The Dark Mod Forums

Linux: Texture and Media Browser GL windows not refreshing


Recommended Posts

This issue has been occurring in the last few weeks, and my first thought was that it is due to a regression that happened during the code reorganisation and the necessary changes to GL context handling. In my Ubuntu 20.10 machine I walked back the git history up to the point of the DR 2.8.0 release, but as it turns out, the problem is happening there too. When switching between Media and Texture tabs, the GL widget is not refreshed, unless you resize the tabs using the splitter between cam and orthoview:

ubuntu20.10.gif

So I launched my other VM running Ubuntu 19.10 and was rather surprised that this problem does not happen there, even with the latest git checkout:

ubuntu19.10.gif

I'm not sure where this behaviour is coming from all of a sudden. While I can't rule out that DR is doing something wrong in terms of context handling, there sure seems to be a difference between the two Ubuntu 19/20 setups. Any suggestions on how to go ahead and find out where the problem is rooted?

The one idea I have: Since Ubuntu 19 is using wxGTK 3.0.4 and Ubuntu 20 is using the latest wxGTK 3.0.5, I will try to compile the older wxWidgets 3.0.4 release from source and use that in the newer Ubuntu 20 version, to see if the problem goes away.

Link to post
Share on other sites

I will see if the issue reproduces on my machine (currently Ubuntu 20.04, I only use LTS releases on my main machine). It looks like the sort of problem that can probably be solved by adding some extra "refresh window" call in a suitable location, even if it isn't entirely obvious why the existing code doesn't work. I seem to remember encountering a similar issue when hiding/showing the 3D camera view toolbar (you'd have to resize the widget before it would actually disappear).

Link to post
Share on other sites

When using the older wxWidgets 3.0.4 in Ubuntu 20.10: problem persists

Whereas in Ubuntu 19.10, where the problem doesn't occur: compiling against the newer wxWidgets 3.0.5: problem occurs

I had to compile wxWidgets 3.0.5 from source in Ubuntu 19.10 and install the libgtk-3-dev package - maybe that's connected to the problem. I'll try to find out what the native Ubuntu 19.10 wxGTK 3.0.4 is compiled against. edit: the package seems to use GTK3.0, so using libgtk-3-dev should be ok.

Link to post
Share on other sites
2 hours ago, OrbWeaver said:

It looks like the sort of problem that can probably be solved by adding some extra "refresh window" call in a suitable location, even if it isn't entirely obvious why the existing code doesn't work

This appears to be pretty close. I set some rConsole output in the TexturePreviewCombo::draw() method, and it is never invoked when selecting different shaders (even though _glWidget->Refresh() is called, which should trigger an OnPaint event.) When resizing, lots of console lines are printed.

I already tried experimentally changing the _glWidget->Refresh() to _glWidget->Update(), which should do an immediate paint, but this doesn't help.

Link to post
Share on other sites

Reproduces for me on Ubuntu 20.04.

I can only assume it's a bug in WxWidgets. The docs are clear: if you call Refresh() on a widget it should queue a paint event, and if you call Update() (possible after calling Refresh() to first invalidate the widget) it should do a repaint immediately. But it refuses to do so. Instead it seems to be queuing the paint events internally somehow, and only releasing them when it feels like it, e.g. in response to resizing or switching to another application.

Or maybe a problem with the underlying GTK/GDK library itself. It seems others have reported similar problems, e.g.

https://stackoverflow.com/questions/13298385/draw-events-not-sent-by-gdk-window-invalidate-rect

https://stackoverflow.com/questions/9009780/c-gtk-window-stops-updating?rq=1

Unfortunately the answers are completely useless.

Link to post
Share on other sites

Some more weirdness: if I switch to another window and back to DarkRadiant, the preview widget suddenly starts to update on selecting textures, exactly as it should. But it never works the first time I start DarkRadiant. It's like the widget starts up in a sort of "standby" state, and doesn't start to get repainted until the window is switched to from another application.

Link to post
Share on other sites

I tried doing it as the docs describe, calling Refresh(false) + Update() afterwards, and it changes the behaviour to be almost correct. With that refresh/update combination, the GLWidget will receive Paint events after the window resize event and it appears to work fine after overcoming this first glitch.

5 hours ago, OrbWeaver said:

Some more weirdness: if I switch to another window and back to DarkRadiant, the preview widget suddenly starts to update on selecting textures, exactly as it should. But it never works the first time I start DarkRadiant. It's like the widget starts up in a sort of "standby" state, and doesn't start to get repainted until the window is switched to from another application.

Yes, exactly this. I compiled a debug build of wxWidgets to see where this is coming from, and after switching back from another application this is happening in the course of idle event processing. It's all bound to the "draw" event that is fired by GTK3+. The same happens when you resize the splitter window - it invalidates some stuff and then the ide processing will issue the OnPaint event.

Reading the wxGTK sources and investigating why this event is not fired immediately, there is some custom expose handling and an "m_exposed" flag in the GLCanvas implementation (it's set to true in the "draw" event handler). The wxWindowGTK::Update() method should trigger a "draw" event by calling gtk_widget_queue_draw_area, but an if-else construct is preventing that from being invoked, so I agree that this is a combination of changed GTK3+ expose behaviour as well as problematic wxWidgets processing code.

Digging further, I saw that all that custom processing code has been removed in 2019. This is not in wx3.0, but part of wx3.1, so I compiled from latest git and voilà, the problem is not happening there.

So, with wxGTK 3.0.x it seems the change to call Update() immediately after Refresh() will improve the behaviour, such that it paints after switching between apps or resizing the splitters. And in wx3.1 the problem is not present at all, whenever that branch will be released. It's been worked on for years now, so that might still be a while.

I'll do some more digging to see if I can artificially trigger that first paint event by force, otherwise I'm going to not spend any more time on that.

Link to post
Share on other sites

Added an additional Update() call in the TexturePreviewCombo and the TextureBrowser, specifically targetted at wxGTK 3.1.2 and earlier. I failed to find anything that could force an artifical size or redraw event, so I'm going to leave it at that.

Link to post
Share on other sites
10 hours ago, greebo said:

I failed to find anything that could force an artifical size or redraw event, so I'm going to leave it at that.

You'd think there would be something in the vast list of public methods on wxWindow, but I could not find anything either.

Things which definitely did not work:

  • _glWidget->PostSizeEvent()
  • _glWidget->Fit()
  • GetSizer()->Layout()
  • _glWidget->Hide() followed by _glWidget->Show()
  • _glWidget->Disable() followed by _glWidget->Enable()
Link to post
Share on other sites

Yeah, I even tried calling SetSashPosition(GetSashPosition() + 1) followed by SetSashPosition(GetSashPosition() - 1), but to no avail. :)

At least there's the silver lining that wx3.1 will get published as stable release sooner or later. Rather later, since the wx team endures long intervals even between minor releases. The project is really alive (which is good for DarkRadiant), but hey, 3.1.0 was published in 2016, and now we're at 3.1.4.

Link to post
Share on other sites

One option would be to move to using our own build of wxWidgets rather than relying on the system version (i.e. basically what I assume we are doing on Windows already, but on Linux too). Since the wxWidgets project is using Git, we wouldn't even need to store a tarball, we could just have a submodule like 3rdparty/wxwidgets which can be checked out automatically.

There would of course be build script work needed to get our configure/automake system to first build the wxWidgets library and then use it instead of the system-wide version, and I don't know if there would be downsides like being unable to use system GTK themes (but I doubt it, because even our own build of wxWidgets would still just be a wrapper for the system-wide GTK 3 libraries). Still, it's an option if enough users complain about this issue and no fixes for the Ubuntu-wide wxWidgets are forthcoming.

Link to post
Share on other sites

Yes, as a last resort this is definitely an option. I'd like to avoid it as long as possible though, since it puts more maintenance work on our shoulders. Would that be even compatible or allowed with the Debian packaging?

(In Windows we're indeed shipping the wx binaries along with DarkRadiant, since there's no package management - though I'm not compiling wxWidgets from source, I'm using the public releases (currently it's 3.1.3 since that includes binaries built with Visual Studio 2019). I still have to compile the libraries like libpng, libxml2, libzlib, freetype, ftgl since some of them don't or at least didn't provide any Windows x64 binaries.)

Link to post
Share on other sites
On 11/27/2020 at 4:52 AM, greebo said:

Yes, as a last resort this is definitely an option. I'd like to avoid it as long as possible though, since it puts more maintenance work on our shoulders. Would that be even compatible or allowed with the Debian packaging?

It would be permitted as long as the libraries we installed did not conflict with system libraries; i.e. we would need to install them somewhere like /usr/lib/darkradiant/libwx_whatever.so rather than in /usr/lib.

But it would definitely be complicated, because not only would we have to build the wxWidgets library (which is pretty straightforward), but build DarkRadiant to link against it in such a way that the correct library would be found at runtime, even though the library location at runtime would be completely different from the library location at build time (which means that a default hard-coded rpath of /home/user/Development/DarkRadiant/wxWidgets/.libs/libwx_whatever.so would be useless, although you might not notice the problem until much later). With a static library you wouldn't need to worry about this, but static linking to wxWidgets is ruled out because we have more than one binary which needs to link against it (including wxutil and several plugins).

So yeah, not something I would want to do unless absolutely necessary.

Link to post
Share on other sites

Just a thought - would it be an adequate solution to distribute DR as an AppImage? There are several programs that I use which are distributed as AppImages (LMMS, Shotcut, OpenXcom), mostly because they simplify the distribution of dependencies on distros which may not have the particular libraries required, or more specifically in this case, require a specific version of a library that's known to work reliably. I like AppImages because while they solve dependency issues, they also don't bother with sandboxing like Snap or Flatpak (so you don't have theming issues or limited access to local filesystems), plus they start much, much faster. Since AppImages are just executables with everything self-contained, you won't have the issue of custom-built libraries spilling out everywhere and possibly causing conflicts for other programs.

A word of warning, Agent Denton. This was a simulated experience; real LAMs will not be so forgiving.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...