Skip to content

Started the Framebuffer API - Am I doing things right so far? #229

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

Closed
wants to merge 2 commits into from

Conversation

torch2424
Copy link
Contributor

@torch2424 torch2424 commented Feb 24, 2020

relates to #174

cc @sunfishcode

What is this PR?

This starts a simple draw syscall for a possible framebuffer API. This is a draft PR where I am more just asking if I seem to be on the right track so far with my implementation on how i can contribute this API.

This (so far) creates: phases/ephemeral/witx/wasi_ephemeral_framebuffer.witx which will be the home for all of the syscalls used by the framebuffer API. And this was tested on my fork of wasmtime on my framebuffer branch.

What is the proposed Framebuffer API?

Please see #174 for more context. But to me, it will eventually become the equivalent of writing directly to something like a linux framebuffer but standardized in WASI.

How did I get this up and running to start contributing?

Josh Triplett's, Extending WASI and wasmtime from WasmSF was a great starting point for me! The technical "how-to contribute" is already out of date. But I still think it is great for the context, and still is somewhat true for what you need to do (covered in my how-to below).

(Per @sunfishcode request) Here's how I was able to import my own WASi syscall to my wasm program, and then run it on my forked wasm runtime:

  1. Fork the WASI repo.
  2. Clone your WASI fork.
  3. Fork the wasmtime repo (Using wasmtime as it was the one used in Josh Triplett's talk).
  4. Clone your wasmtime fork using the build instructions on wasmtime.dev.
  5. In your WASi fork, implement your syscall in a .witx file in : phases/ephemeral/witx (For example, here is my initial draw syscall).
  6. In your wasmtime fork, that you correctly made sure to get the submodules for when you cloned it, implement this same syscall in the latest snapshot. In my case it was in: crates/wig/WASI/phases/snapshot/witx/wasi_snapshot_preview1.witx. NOTE: We are implementing this in the latest snapshot so there is less you have to do to have wasmtime allow it.
  7. In your wasmtime fork, implement the actual function that does the logic of your syscall in: crates/wasi-common/src/hostcalls_impl/misc.rs. (For example, here is my "println does it work?" draw syscall implementation)
  8. Build your wasmtime fork using the instructions in wasmtime.dev (NOTE: I had to use Rust nightly).
  9. Write a wasm module that calls your WASI syscall (For example, here is my draw.wat compiled with wat2wasm)
  10. Run your compiled wasm module with your compiled wasmtime fork (wasmtime executable should be in target/release/wasmtime). For Example: ./target/release/wasmtime ../wasi-syscall-playground/draw.wasm.
  11. Your syscall should be run! 😄

Results

Screenshot from 2020-02-24 01-50-32

EDIT: Meant to make a draft PR, but I clicked the wrong button, and there is no way to go back. Closing for now, and I'll keep working on it until it is actually ready and re-open?

@torch2424 torch2424 closed this Feb 24, 2020
@programmerjake
Copy link
Contributor

I would suggest having an API where you can:

  • map_buffer: convert a passed-in memory region to a memory-mapped buffer with a particular pixel format and layout kind, which can be implemented by remapping a region of the linear memory to point to the HW video ram if the HW supports that (can use mmap to remap a region on Linux), or just leave it as plain system ram. There could also be an option of just returning a pointer to a different address rather than requiring allocated memory to be passed in.

  • unmap_buffer: tear down the stuff done by map_buffer

  • start_update: start an update to the display with the following parameters:

    • modified_rect: a passed-in rectangle as a hint for which region was modified, used to reduce power consumption for partial updates
    • display_from_location: the location in the memory-mapped buffer to display from, allows page-flipping and limited scrolling.
  • wait_for_last_update: waits for the operation initiated by the last start_update. not necessary to call wait_for_last_update for the display update to complete. This can be used to limit rendering speed to the refresh rate of the display if the updates started by start_update wait till the next refresh.

The displayed output may be updated at any time from the last display_from_location without any calls to start_update (eg. the mapped memory is video ram and whatever is written is displayed right away).
Any displayed output pixels are not guaranteed to be updated after writing to the buffer unless start_update is called with the pixels included in modified_rect.

There will also need to be functions to get attributes such as:

  • output size in pixels
  • output size in millimeters (for proper scaling and handling non-square pixels)
  • required memory-mapped buffer size and alignment for different pixel formats and number of pages for page-flipping.
  • allowed pixel formats
  • allowed display_from_location values

there is obviously more stuff that I didn't include or overlooked.

@programmerjake
Copy link
Contributor

EDIT: Meant to make a draft PR, but I clicked the wrong button, and there is no way to go back. Closing for now, and I'll keep working on it until it is actually ready and re-open?

@torch2424
It would probably be better to reopen but change the title to begin with WIP: , since that improves visibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants