The goal is to have a basic "framebuffer driver" for mnemos.
I think this would work something like:
- use the embedded graphics simulator, or similar sdl2/web tech to build a gui window
- use embedded-graphics (and maybe embedded-text) as graphics primitives
- provide some kind of interface to draw to the frame buffer, such as:
- providing an X/Y start coord, and a rectangle to be painted on to the frame buffer
- provide a way to provide a "full frame update" (this might just be the other option starting at (0, 0) and fully sized).
I think mostly, you'll want a "whole framebuffer", say 800x600, and you should take smaller rectangle chunks of arbitrary size, and draw them to the frame buffer. This way your "demo task" can draw something like a 320x240 chunk using embedded-graphics, and just paint that on to the large, "dumb" framebuffer.
To do this, you will likely need to do the following (short summary):
- Add a new driver to the kernel that owns the frame buffer and whatever window context that needs to exist.
- Define a message type for sending update commands.
- Process incoming commands, update the framebuffer, redraw the framebuffer whenever updated
- Provide some kind of demo that draws something, or does an animation, or takes data from a virtual port or something and draws it
Longer summary:
make a driver
misc note: The simulator is called "melpomene". You can find it in source/melpomene
. You can run it with MELPOMENE_TRACE=trace cargo run
. You'll see a lot of tracing
events there. If you want to see a lot more, check out this comment which will show you how to run the virtual serial ports that are already working in the simulator.
Drivers in mnemos are basically just async tasks. "real drivers" should be self contained, but for the simulator, you can use whatever. You can spawn threads if you want, and we also have a tokio runtime going that provides sleep and uart stuff.
Check out the sim drivers folder for simulator specific drivers, and kernel drivers for real drivers. You'll probably want to use the Heap types to allocate your frame buffer.
Don't worry about getting any of this perfect yet.
Once you have a driver, you'll probably need to set it up in the initialization function, and spawn it into the kernel's executor. Check out [kernel_entry()
](https://github.com/tosc-rs/mnemos/blob/09ef1595527a388fd01ea3bfdc6741561f4a8a04/source/melpomene/src/main.rs#L68) in melpo for how other tasks do this. You might also need to modify how much memory is given to the kernel at initialization. Go ahead and bump it to like 16MiB or whatever you need.
Define message types
mnemos has two main communication channels you'll see. One is stream based, and that's all the ones you see called bbq
. I don't think you'll need those for this. The other one is basically an MPSC async queue, called KChannel. You can basically create a kchannel that contains your type (and optionally a "reply" channel producer), and define whatever message types you want. Since it'll probably be relatively "big" buffers, your message should probably also use heap types for this.
You can see an example of a message type in the serial_mux driver, and how a kchannel is used in the current main task.
You might want to have something like a FrameChunk
, which holds an appropriately sized heap allocation, and implements that DrawTarget trait from e-g.
This way you could do something like:
// this makes a 320 x 240 x 2 allocation to act as a 16bpp frame chunk
let mut new_frame = FrameChunk::new(320, 240).await;
// This uses e-g methods to paint this sub-frame
Circle::new(...)
.whatever(...)
.eg(...)
.methods(...)
.draw(&mut new_frame).unwrap();
// send the sub-frame over the kchannel
driver_producer.send(Command::Draw { x: 0, y: 100, chunk: new_frame }).await.unwrap();
Process incoming commands
Again, the serial mux driver is a good example of accepting messages and doing stuff with them. Here you will do whatever your framebuffer logic stuff is.
Provide some kind of demo
Right now, userspace isn't up and running. So just define some async demo task (in melpo's main, or somewhere else), that holds the new driver's kchannel producer, and draw something every 1 second or so.
good first issue help wanted