canselcik / libremarkable

The only public framework for developing applications with native refresh support for Remarkable Tablet
MIT License
616 stars 56 forks source link

Is it possible to avoid clearing the screen when starting an app ? #105

Closed X-Ryl669 closed 11 months ago

X-Ryl669 commented 2 years ago

Ideally, I'd like to pop up a calculator widget upon gesture recognition, so to avoid disrupting the current flow, I'd like to capture what's actually on the hardware framebuffer while starting the app, and use that as a background image. So, is it possible to:

  1. Capture the hardware framebuffer before it's actually messed up by the application?
  2. Start the application without flashing the screen (so it's not disturbing)?
LinusCDE commented 2 years ago

Hi,

I don't see a problem with this. The application should only draw over stuff it needs to.

If you just need a specific rectangular area, you don't need to clean the remaining framebuffer at all.

If you use the libremarkable::framebuffer::FramebufferIO-Trait (Doc), you have access to read_pixel, write_pixel. Edit: There are also dump_region and restore_region which provide or overwrite the raw pixel data of a specified region.

  1. Capture the hardware framebuffer before it's actually messed up by the application?

Should be easy by doing a dump_region() of the entire framebuffer and a restore_region() later.

  1. Start the application without flashing the screen (so it's not disturbing)?

You can use partial_refresh() which is provided by the libremarkable::framebuffer::FramebufferRefresh-Trait (Doc). Most values are documented, but finding a kind of refresh that suits your app best with minimal delay is mostly going be feeling and trial & error imo.

Here are some examples, that use this method:

On the rM 2, the remarkable-framebuffer project is the shim that is used for all homebrew stuff. It fakes the framebuffer of the rM 1 and maps the refresh modes it to fewer ones. The mapping code can be found here.

Aside regarding transparent images

If you need something that can leave gaps or want rounded shapes that preserve the background, you need to manually calculate new pixels and take the old ones into account. I had that problem already when making chessmarkable, so I added methods for that to my canvas helper class here. Feel free to just copy the code as you please. You use that to overlay any transparent image over the existing framebuffer. I already did a bunch of performance testing on that, and using fixed digits instead of floats does not give any performance benefit as the fpu (called neon) seemingly is just that fast already. I used the dump_region there to reduce the needed read pixel operations though.

The screenshot example might also prove useful as it also turns the framebuffer into an image (the srgb/gamma mapping is nice to have, but not needed to be functional).

Edit: Some clarifcations and grammar fixes

X-Ryl669 commented 2 years ago

Thanks a lot for your detailed answer!

LinusCDE commented 11 months ago

Since this has been answered, this issue is probably long overdue for closure. Feel free to ask follow-up questions if needed though.