Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sdl] missing frames #165

Open
zenria opened this issue Apr 24, 2022 · 1 comment
Open

[sdl] missing frames #165

zenria opened this issue Apr 24, 2022 · 1 comment
Labels
bug Something isn't working

Comments

@zenria
Copy link
Contributor

zenria commented Apr 24, 2022

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):
surface_saved

And here is the screenshot of the actual window:
Capture d’écran 2022-04-24 à 18 18 04

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.

@jmmv
Copy link
Collaborator

jmmv commented Apr 24, 2022

Thanks for the report and the analysis.

I'm no SDL expert and I can see what I did to render to the screen is problematic. Mind you, my first versions of the code did what the documentation suggests: render directly to the screen. The problem then is that I couldn't find a way to "scrape" the existing screen contents to implement scrolling, hence why I had to shift to drawing onto a surface.

Note how in the "model" you listed above, you are supposed to draw the whole scene from scratch on every frame, which is pretty much impossible here. If we only had to draw the text console, it'd be rather easy, but once we mix overlapping graphics... we'd essentially have to keep a copy of the screen's bitmap somewhere to be able to redraw it from scratch---which is what the separate surface achieves.

I'm open to better answers to this but I couldn't find any. But again, I'm no SDL expert.

@jmmv jmmv added the bug Something isn't working label Apr 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants