-
Notifications
You must be signed in to change notification settings - Fork 147
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
Fixed issue with image buffers not being displayed properly #1795
base: main
Are you sure you want to change the base?
Conversation
Since screen_event_clear() only puts item a request into a queue it turns out that the clearing of the screen can actually not be finished until after the next screen command has started. This is especially apparent if the next screen command is screen.display_image() for displaying a buffer. Frequently the end result is that the image buffer is not displayed at all or only part of it becomes visible. Therefore need to execute a command that gets a return value to make sure that the screen has finished being cleared before this function returns. Using _screen_current_point() here completely fixes the problem. Wanted to just look at the screen queue to see if there was a way to wait until the queue was cleared but there did not appear to be such a solution.
It appears that during previous round of screen changes that screen_surface_display() was modified to include surface_may_have_color=true. But screen_surface_display() does the exact same thing, and therefore should be consistent. Therefore made the code consistent in order to avoid problems from cropping up.
i'm not confident enough to speak on the screen redraw backend, but wanted to add that @skibu 's changes test well for me -- seems like a very sensible solution! i was able to get |
I wouldn't say the necessity is by design, but rather a consequence of moving Cairo operations into its own thread and some of the functions were required to be blocking asynchronous. Some of the open GH issues about screen seem related. I'll need to get back into the code a little bit before I can say whether or not it's a good idea to call There are definitely some subtle timing things to work out with the screen that are probably beyond the scope of this particular PR. I'll check in here again soon. |
The solution might be to give all screen functions in weaver an event so that screen operations happen sequentially. Specifically EDIT: Yeah, that seems to do the trick. |
@@ -636,6 +636,9 @@ bool screen_surface_get_extents(screen_surface_t *s, screen_surface_extents_t *e | |||
|
|||
void screen_surface_display(screen_surface_t *s, double x, double y) { | |||
cairo_surface_t *image = (cairo_surface_t *)s; | |||
|
|||
surface_may_have_color = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good call to make this function color aware. I think it may be worthwhile to extend screen_surface_t
into an actual struct that holds may_have_color
as a boolean, and a pointer to the cairo surface. Right now, it just appears that screen_surface_t
is just an alias for cairo_surface_t
.
Doing this would avoid any unnecessary color conversions in the case where screen_surface_display()
is called on a surface that was not constructed from a PNG.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think would be great to do this in a separate PR.
2024-08-08_norns_pr_1795_d.patch Here's a patch that adds two more screen events, one for |
I’ll try out @tlubke ’s patch in a bit. I’m pretty confident that adding the new screen events is the proper solution. I can see how making functions like Btw, I had also tried just using screen_results_wait(). It deadlocking meant that I needed a command that retrieved data in order to sync the commands. |
This code change was purely done by @tlubke. It addresses the issue of making sure a display image buffer command doesn't happen until the screen clear command has been executed. This was done by making the display image buffer commands events, which means they are processed by the event queue sequentially. Tested this change for PR monome#1795 and it works great. Reverted my original proposed change in weaver.c.
Thanks awesome Yes, queing everything is better than blocking the caller (main thread) |
Probably a good time to cross off #1747 too. I got started on it and modified scrollImageBuffer.lua to use I'll push a branch and see what people think. tlubke@a995249 EDIT: I removed |
Video is worth a thousand words so here is what it is supposed to look like: https://youtu.be/81JUmu6EaWg
And here is what it looks like using an image buffer. Quite disappointing. https://youtu.be/W6i9Ffs2YzA
Please provide feedback if you have additional suggestions.
I tried to implement the dynamic scrolling of some pretty pictures in my Norns script that is under development. In order to do some interesting things graphically I tried reading in a PNG file into an image buffer, and then just writing the image buffer to the screen using screen.display_image(). The images showed up, but maybe a quarter of the time I just got a blank screen or just the lower part of the image. It was quite disappointing and not very pretty at all.
I did lots of exploring and testing and found that there is a timing issue. Screen commands are not executed fully immediately. Instead, they are queued and then processed by Cairo. It means that after doing a screen.clear() and then immediately afterwards a screen.display_image(png_buffer, x, y) that the clearing of the screen hadn't yet been completed. This resulted sometimes in the image buffer being overwritten by the clearing of the screen that was still in process. Likely, this is also occurring for other graphics operations, but just not yet noticed by anyone.
The solution was to change weaver.c _screen_clear() so that it doesn't return until the clear has been processed. I found that putting in a delay after the screen_clear() fixed the problem, but a delay is of course not a desirable solution. Since don't have good access to the workings of the screen queue, nor to Cairo, I found that needed to use a screen command that waits for results. This of course makes sure that the previous clear event is done. I chose the simplest screen function that returns a value, which is _screen_current_point().
The difference is like night and day. With the simple change to weaver.c the image buffer is always drawn correctly.
I created two scripts to illustrate the problem and the solution. Scripts are at https://github.com/skibu/nornsFun and are scrollImageFile.lua and scrollImageBuffer.lua .
scrollImageFile.lua shows what it is supposed to look like and doesn't actually use an image buffer. But scrollImageBuffer.lua will show the problem. And you can try the simple change to weaver.c to see how scrollImageBuffer.lua works with the change.
And lastly, I made screen.c consistent and added
surface_may_have_color = true;
to screen_surface_display(). I think it was previously just an oversight from when other screen changes were made a few months ago.