Description
I'm currently testing the SDL console on macos.
Sometimes, rendered surface seems not to be presented to the window. It happens more likely in REPL when 2 lines are printed without any user interaction. (Typically, "Ready" is not displayed)
I tracked the issue deeply in the code to check is there was a missing call to present_canvas()
. Everything seems alright.
With the following code at the very end of force_present_canvas()
, I managed to reproduce the issue:
self.canvas.surface().save_bmp("screen.bmp").map_err(string_error_to_io_error)
So here is the rendered BMP (everything is OK here):
And here is the screenshot of the actual window:
The "Ready" prompt is missing! It has correctly been rendered in the underlying surface, but is not shown to the actual window! If I hit a key, let's say "B" the Ready prompt is correctly render and the "B" letter is shown at the right place...
I initially thought the issue was coming from the unusual way to render to the window (rendering to a surface and then blitting the surface to the window surface). SDL documentation and example wants you to render directly to a window canvas typically created by calling window.into_canvas().build()
. This is also the way to enable hardware acceleration and Rust SDL documentation emphasizes that rendering to a surface is slow and not accelerated. So I heavily modified the code to do the rendering to a window canvas and to present the canvas.
This did not work! Same issue.
I then read a bunch of example of SDL code. In all example, the render is always done the same way:
- consume all events
- render the whole scene
- wait some time to achieve 30 or 60 fps
- present the canvas
The critical part missing from the endbasic SDL rendering code is the wait time. I confirmed this by adding a dumb std::thread::sleep
in force_present_canvas()
function. No more missing frames.
I'm not sure how to fix this. I think the best way would be to have a dedicated thread that does main loop the way sdl wants it to be (poll events/render/wait/present) and communicates with the rest of endbasic (the Console
trait impl) with channels.