I'm writing a program that has an X11/Xlib interface, and my event processing loop looks like this:
while (XNextEvent(display, &ev) >= 0) {
switch (ev.type) {
// Process events
}
}
The problem is when the window is resized, I get a bunch of Expose events telling me which parts of the window to redraw. If I redraw them in direct response to the events, the redraw operation lags terribly because it is so slow (after resizing I get to see all the newly invalidated rectangles refresh one by one.)
What I would like to do is to record the updated window size as it changes, and only run one redraw operation on the entire window (or at least only two rectangles) when there are no more events left to process.
Unfortunately I can't see a way to do this. I tried this:
do {
XPeekEvent(display, &ev);
while (XCheckMaskEvent(display, ExposureMask | StructureNotifyMask, &ev)) {
switch (ev.type) {
// Process events, record but don't process redraw events
}
}
// No more events, do combined redraw here
}
Which does actually work, but it's a little inefficient, and if an event arrives that I am not interested in the XCheckMaskEvent call doesn't remove it from the queue, so it stays there stopping XPeekEvent from blocking, resulting in 100% CPU use.
I was just wondering whether there is a standard way to achieve the delayed/combined redraw that I am after? Many of the Xlib event processing functions seem to block, so they're not really suitable to use if you want to do some processing just before they block, but only if they would block!
EDIT: For the record, this is the solution I used. It's a simplified version of n.m.'s:
while (XNextEvent(display, &ev) >= 0) {
switch (ev.type) {
// Process events, remember any redraws needed later
}
if (!XPending(display)) {
// No more events, redraw if needed
}
}
FWIW a UI toolkit such as GTK+ does it this way:
for each window, maintains a "damage region" (union of all expose events)
when the damage region becomes non-empty, adds an "idle handler" which is a function the event loop will run when it doesn't have anything else to do
the idle handler will run when the event queue is empty AND the X socket has nothing to read (according to poll() on ConnectionNumber(dpy))
the idle handler of course repaints the damage region
In GTK+, they're changing this over to a more modern 3D-engine oriented way (clean up the damage region on vertical sync) in a future version, but it's worked in the fairly simple way above for many years.
When translated to raw Xlib, this looks about like n.m.'s answer: repaint when you have a damage region and !XPending(). So feel free to accept that answer I just figured I'd add a little extra info.
If you wanted things like timers and idles, you could consider something lke libev http://software.schmorp.de/pkg/libev.html it's designed to just drop a couple of source files in your app (it isn't set up to be an external dependency). You would add the display's file descriptor to the event loop.
For tracking damage regions, people often cut-and-paste the file "miregion.c" which is from the "machine independent" code in the X server. Just google for miregion.c or download the X server sources and look for it. A "region" here is simply a list of rectangles which supports operations such as union and intersect. To add damage, union it with the old region, to repair damage, subtract it, etc.
Try something like the following (not actually tested):
while (TRUE) {
if (XPending(display) || !pendingRedraws) {
// if an event is pending, fetch it and process it
// otherwise, we have neither events nor pending redraws, so we can
// safely block on the event queue
XNextEvent (display, &ev);
if (isExposeEvent(&ev)) {
pendingRedraws = TRUE;
}
else {
processEvent(&ev);
}
}
else {
// we must have a pending redraw
redraw();
pendingRedraws = FALSE;
}
}
It could be beneficial to wait for 10 ms or so before doing the redraw. Unfortunately the raw Xlib has no interface for timers. You need a higher-level toolkit for that (all toolkits including Xt have some kind of timer interface), or work directly with the underlying socket of the X11 connection.
Related
I'm having issues with my termbox program rendering the screen and handling keyboard events. Recently, I've finished a C and C++ class at my university. I wanted to demonstrate my knowledge by creating a basic Snake game. The first steps, I wanted to get a simple render loop going and have a block of text simply move leftward and exit the game upon reaching the 0th x-coordinate. The issue arises when continuing to the next render frame, because the game is running single-threaded the next frame won't be rendered until a new keyboard event is accepted. Ordinarily, I would expect the game to continue rendering regardless of events, new events affecting the new frame.
As for potential solutions, I thought about using multiple threads to run the game loop and handle keyboard events. But, I think this would be overkill for such a small problem, there are likely easier alternatives than having to manage multiple threads for a simple snake game.
As for the code, it's as simple as:
while (1)
{
tb_clear();
draw(gameState);
tb_present();
struct tb_event event;
tb_poll_event(&event);
if (event.ch == 'q')
break;
}
After digging through the header file a bit more I found a method which doesn't wait forever.
/* Wait for an event up to 'timeout' milliseconds and fill the 'event'
* structure with it, when the event is available. Returns the type of the
* event (one of TB_EVENT_* constants) or -1 if there was an error or 0 in case
* there were no event during 'timeout' period.
*/
SO_IMPORT int tb_peek_event(struct tb_event *event, int timeout);
I'm working on a library that creates transparent X windows and uses cairo to draw on them. There is an event loop implemented in the main thread, while the drawing operations take place in a separate thread within a loop. The latter looks like this
while (self->_running) {
PyGILState_Release(gstate);
usleep(1000); // Sleep 1 ms
gstate = PyGILState_Ensure();
if (self->_expiry <= gettime()) {
draw(self, args_tuple); // All the cairo code is in here
self->_expiry += interval;
interval = self->interval;
}
}
The event loop calls XNextEvent periodically to trap key/button presses only. The window is mapped before the new UI thread is started from the main thread.
When the interval between iterations on the UI thread (the self->inteval value above) is large (order of seconds), the window stays transparent on the first iteration of the loop, and it only gets painted on from the second iteration onward. Calling draw right before the while loop doesn't help, unless there is a pause of some milliseconds in between calls to draw. For example, if I put interval = 25 right before the while loop, then the second call to draw paints on the window in most of the executions of the application implementing this code.
Things that I have tried:
cairo_surface_flush and XFlush right after draw don't seem to work
Sending an Expose event doesn't seem to help either.
How can I make sure that my loop starts painting on the window from the first iteration?
What I'm missing is the ExposureMask flag in the call to XSelectInput. With this flag set, one then has to look for Expose events in the event loop with the following pattern:
switch (e.type) {
case Expose:
if (e.xexpose.count == 0) {
BaseCanvas__redraw(canvas);
}
return;
}
The redraw operation doesn't need to be the full set of draw operations. Having modified the cairo context, it is enough to repaint it on the destination with no more than this
void
BaseCanvas__redraw(BaseCanvas * self) {
cairo_save(self->context);
cairo_set_operator(self->context, CAIRO_OPERATOR_SOURCE);
cairo_paint(self->context);
cairo_restore(self->context);
}
To me it looks like you are mapping the window and then immediately starting a thread that tries to draw to the window. Thus, if you try to draw before the window manager actually made the window visible, your drawing goes nowhere. If the window manager wins the race and the window actually becomes visible before your draw, the drawing actually works.
Your own answer is not an answer to your question. The question is "why does it stay transparent in the first iteration?" while your answer is (basically) "Don't use threads, just do all drawing in the main loop".
(Of course, handling Expose events is the right thing to do, but that's not what the question asked.)
I am using the SharpDX.WPF project for the WPF abilities, it seems like an easy to understand low-overhead library, compared to the Toolkit that comes with SharpDX (which has the same issue!)
First: I fixed the SharpDX.WPF project for the latest SharpDX using the following: https://stackoverflow.com/a/19791534/442833
Then I made the following hacky adjustment to DXElement.cs, a solution that was also done here:
private Query queryForCompletion;
public void Render()
{
if (Renderer == null || IsInDesignMode)
return;
var test = Renderer as D3D11;
if (queryForCompletion == null)
{
queryForCompletion = new Query(test.Device,
new QueryDescription {Type = QueryType.Event, Flags = QueryFlags.None});
}
Renderer.Render(GetDrawEventArgs());
Surface.Lock();
test.Device.ImmediateContext.End(queryForCompletion);
// wait until drawing completes
Bool completed;
var counter = 0;
while (!(test.Device.ImmediateContext.GetData(queryForCompletion, out completed)
&& completed))
{
Console.WriteLine("Yielding..." + ++counter);
Thread.Yield();
}
//Surface.Invalidate();
Surface.AddDirtyRect(new Int32Rect(0, 0, Surface.PixelWidth, Surface.PixelHeight));
Surface.Unlock();
}
Then I render 8000 cubes in a cube pattern...
Yielding...
gets printed to the console quite often, but the flickering is still there.
I am assuming that WPF is nice enough to show the image using a different thread before the rendering is done, not sure though...
This same issue also happens when I use the Toolkit variant of WPF support with SharpDX.
Images to demonstate the issue:
Bad
Better
Almost
Intended
Note: It randomly switches between these old images, randomly. I am also using really old hardware which makes the flickering much more appearant (GeForce Quadro FX 1700)
A made a repo which contains the exact same source-code as I am using to get this issue:
https://github.com/ManIkWeet/FlickeringIssue/
Related to D3DImage locking, note that the D3DImage.TryLock API has rather unconventional semantics which most developers would not expect:
Beware!
You must call Unlock even in the case where TryLock indicates failure (i.e., returns false)
Although perhaps more of an alarming design choice than a bug per se, misunderstanding this behavior will trivially result in D3DImage deadlocks and hangs, and thus might be responsible for much of the frustration people experience in attempting to get D3DImage working properly.
The following code is a correct WPF D3D render with no flicker in my app:
void WPF_D3D_render(IntPtr pSurface)
{
if (TryLock(new Duration(default(TimeSpan))))
{
SetBackBuffer(D3DResourceType.IDirect3DSurface9, pSurface);
AddDirtyRect(new Int32Rect(0, 0, PixelWidth, PixelHeight));
}
Unlock(); // <--- !
}
Yes, this unintuitive code is actually correct; it is the case that that D3DImage.TryLock(0) leaks one internal D3D buffer lock every time it returns failure. You don't have to take my word for it, here's the CLR code from PresentationCore.dll v4.0.30319:
private bool LockImpl(Duration timeout)
{
bool flag = false;
if (_lockCount == uint.MaxValue)
throw new InvalidOperationException();
if (_lockCount == 0)
{
if (timeout == Duration.Forever)
flag = _canWriteEvent.WaitOne();
else
flag = _canWriteEvent.WaitOne(timeout.TimeSpan, false);
UnsubscribeFromCommittingBatch();
}
_lockCount++;
return flag;
}
Notice that the internal _lockCount field is incremented regardless of whether the function returns success or failure. You have to call Unlock() yourself, as shown in the first code example above, if you want to avoid certain deadlock. Failing to do so creates is nasty to debug, too, because the component won't (potentially) deadlock until the next render pass, by which time the relevant evidence is long gone.
The unusual behavior does not seem to be mentioned at MSDN, but to be fair, that documentation doesn't note that you have to call Unlock() if the call is successful, either.
The problem is not the Locking mechanism. Normally you use Present to draw to present the image. Present will wait until all drawing is ready. With D3DImage you are not using the Present() method. Instead of Presenting, you lock, adding a DirtyRect and unlock the D3DImage.
The rendering is done asynchrone so when you are unlocking, the draw actions might not be ready. This is causing the flicker effect. Sometimes you see items half drawn. A poor solution (i've tested with) is adding a small delay before unlocking. It helped a little, but it wasn't a neat solution. It was terrible!
Solution:
I continued with something else; I was expirimenting with MSAA (antialiasing) and the first problem I faced was; MSAA cannot be done on the dx11/dx9 shared texture, so i decided to render to a new texture (dx11) and create a copy to the dx9 shared texture. I slammed my head on the tabel, because now it was anti-aliased AND flicking-free!! Don't forget to call Flush() before adding a dirty rect.
So, creating a copy of the texture: DXDevice11.Device.ImmediateContext.ResolveSubresource(_dx11RenderTexture, 0, _dx11BackpageTexture, 0, ColorFormat); (_dx11BackpageTexture is shared texture) will wait until the rendering is ready and will create a copy.
This is how I got rid of the flickering....
I think you are not locking properly. As far as I understand the MSDN documentation you are supposed to lock during the entire rendering not just at the end of it:
While the D3DImage is locked, your application can also render to the Direct3D surface assigned to the back buffer.
The information you find on the net about D3DImage/SharpDX is somewhat confusing because the SharpDX guys don't really like the way D3DImage is implemented (can't blame them), so there are statements about this being a "bug" on Microsofts side when its actually just improper usage of the API.
Yes, locking during rendering has performance issues, but it is probably not possible to fix them without porting WPF to DirectX11 and implementing something like a SwapChainPanel which is available in UWP apps. (WPF itself still runs on DirectX9)
If the locking is a performance issue for you, one idea I had (but never tested) is that you could render to an offscreen surface and reduce the lock duration to copying that surface over to the D3DImage. No idea if that would help performance wise but its something to try.
I've got a little GTK-Application with two buttons (A, B) and a drawing area (C).
When I click on A, C's size should be recalculated and set with gtk_widget_set_size_request(). This will cause an expose-event, whose handler will calculate some data. Further, the click on A will emit a clicked signal at B, whose handler needs the data calculated by C's expose-event.
In fact everything works fine, but the expose-event delays somehow, and the clicked handler is called before and the data (you may guess it) is missing.
a_handler() {
new_size = calculate_size();
gtk_widget_set_size_request(C, new_size); //Will cause expose-event
g_signal_emit_by_name(B, "clicked");
}
b_handler() {
calculate_something(data); //Error
}
c_handler() {
draw_something();
data = calcluate_data();
}
What can I do?
Gtk (and most other GUI toolkits) does the painting and event handling all in one thread. Therefore when the expose event is emitted, it goes into a queue and will be handled only after a_handler returns.
The best approach in my opinion would be to move the calculation somewhere else, if there is not some good reason to tie it into GUI drawing. For example, there could be a separate method calculate_data that is called both from b_handler and c_handler.
The next best way is to call gdk_window_process_updates to force the expose event to be handled immediately:
http://developer.gnome.org/gdk/stable/gdk-Windows.html#gdk-window-process-updates
The ugly fix is typically to add calls to gtk_main_iteration(), for instance between the call to gtk_widget_set_size_request() and the signal-emission.
I'm writing an open source C library. This library is quite complex, and some operations can take a long time. I therefore created a background thread which manages the long-running tasks.
My problem is that I have not yet found an elegant way to return errors from the background thread. Suppose the background thread reorganizes a file or does periodic maintenance, and it fails – what to do?
I currently see two options:
1) if the user is interested in seeing these errors, he can register a callback function.
I don't like this option – the user doesn't even know that there's a background thread, so he will most likely forget about setting the callback function. From usability point of view, this option is bad.
2) the background thread stores the error in a global variable and the next API function returns this error.
That's what I'm currently doing, but I'm also not 100% happy with it, because it means that users have to expect EVERY possible error code being returned from every API function. I.e. if the background thread sets an IO Error, and the user just wants to know the library version, he will get an IO error although the get_version() API call doesn't access the disk at all. Again, bad usability…
Any other suggestions/ideas?
Perhaps for the "long running operations" (the ones you'd like to use a thread for) give users two options:
a blocking DoAction(...) that returns status
a non-blocking DoActionAsync(..., <callback>) that gives the status to a user provided callback function
This gives the user the choice in how they want to handle the long operation (instead of you deciding for them), and it is clear how the status will be returned.
Note: I suppose that if they call DoActionAsync, and the user doesn't specify a callback (e.g. they pass null) then the call wouldn't block, but the user wouldn't have/need to handle the status.
I am interested in knowing how the completion status informed to the caller of API.
Since the background thread carries out all the execution. Either the foreground thread chooses to wait till the completion, like synchronous. Or the foreground thread can do other tasks, registering for a callback.
Now, since the first method is synchronous, like your usage of a global variable. You can use a message queue with 1 member, instead of your global variable. Now,
- Caller can either poll the message queue for the status
- Caller can block wait on the message queue for status
What I can think of,
But if I am the caller, I would like to know the progress status, if the time taken is very ... very long. So better to give some kind of percentage completion or something to enable the end user to develop much better application with progress bar and all.
You should keep a thread-safe list (or queue) of error events and warnings. The worker thread can post events to the list, then the main thread can read events from the list, one at a time, or in a batch to prevent race conditions. Ideally, the main thread should fetch a copy of the event queue and flush it so there is no change of duplicating events in the case of multiple main or worker threads. Events on the list would have a type and details.
If you're providing a library and try to hide expensive work via a thread I'd suggest to not do it that way. If something is expensive it should be visible to the caller and if it bugs him, he should take care of backgrounding/threading himself. That way he also has full control over the error.
It also takes the control over his process away from the developer who uses your library.
If you still want to use threads I'd suggest to really follow the callback-route but make it clearly visible in the API and documentation that there will be a background thread running on this task and therefore the callback is necessary.
Best way would be if you offered both ways, synchronous and asynchronous, to the users of the library so they can choose what fits best for them in their specific situation.
Thanks for all the good answers. You provided me with a lot of material to think about.
Some of you suggested callbacks. Initially, i thought a callback is a good idea. But it just moves the problem to the user. If a user gets an asynchronous error notification, how will he deal with it? he will have to interrupt and/or notify his synchronous program flow, and that's usually tricky and often breaks a design.
The solution i'm doing now: if the background thread generates an error, the next API call will return an error BACKGROUND_ERROR_PENDING. With a separate API function (get_background_error()) the user can look at this error code, if he's interested in it.
Also, i added documentation so users don't be too surprised if this error is returned.
You might take a look at java's Future API for an alternate mechanism for dealing with asynchronous calls and errors. You could easily substitute the checked exceptions with some isError() or getError() methods if you preferred.
I agree with Sean. An message queue with an event loop.
If there is an error the background thread can insert into the queue. The event loop will block until a new message becomes available.
I have used Apache Portable runtime time with great success with this design in building telecomms servers with a high transaction rate. It has never failed.
I use 1 thread to inserting into the queue, that would be your background thread. The event loop will run in another thread and block until a new message is inserted.
I would recommend APR thread pool with APR FIFO queue (which is also thread safe).
Quick design here:
void background_job()
{
/* There has been an error insert into the queue */
apr_status_t rv = 0;
rv = apr_queue_push(queue, data);
if(rv == APR_EOF) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue has been terminated");
return FALSE;
}
else if(rv == APR_EINTR) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue was interrupted");
return FALSE;
}
else if(rv != APR_SUCCESS) {
char err_buf[BUFFER_SIZE];
MODULE_LOG(APK_PRIO_CRITICAL, "Failed to push to queue %s", apr_strerror(rv, err_buf, BUFFER_SIZE));
return FALSE;
}
return TRUE;
}
void evt_loop()
{
while(continue_loop) {
apr_status_t rv = 0;
rv = apr_queue_pop(queue, data);
if(rv == APR_EOF) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue has been terminated");
return FALSE;
}
else if(rv == APR_EINTR) {
MODULE_LOG(APK_PRIO_WARNING, "Message queue was interrupted");
return FALSE;
}
else if(rv != APR_SUCCESS) {
char err_buf[BUFFER_SIZE];
MODULE_LOG(APK_PRIO_CRITICAL, "Failed to pop from the queue %s", apr_strerror(rv, err_buf, BUFFER_SIZE));
return FALSE;
}
return TRUE;
}
}
Above is just some simple code snippets, if you want I post more complete code.
Hope that helps