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

Android backend #130

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Android
/src/android.rs @MarijnS95

# Apple platforms
/src/cg.rs @madsmtm

Expand Down
46 changes: 23 additions & 23 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,38 +73,38 @@

# 0.3.0

* On MacOS, the contents scale is updated when set_buffer() is called, to adapt when the window is on a new screen (#68).
* **Breaking:** Split the `GraphicsContext` type into `Context` and `Surface` (#64).
* On Web, cache the document in the `Context` type (#66).
* **Breaking:** Introduce a new "owned buffer" for no-copy presentation (#65).
* Enable support for multi-threaded WASM (#77).
* Fix buffer resizing on X11 (#69).
* Add a set of functions for handling buffer damage (#99).
* Add a `fetch()` function for getting the window contents (#104).
* Bump MSRV to 1.64 (#81).
- On MacOS, the contents scale is updated when set_buffer() is called, to adapt when the window is on a new screen (#68).
- **Breaking:** Split the `GraphicsContext` type into `Context` and `Surface` (#64).
- On Web, cache the document in the `Context` type (#66).
- **Breaking:** Introduce a new "owned buffer" for no-copy presentation (#65).
- Enable support for multi-threaded WASM (#77).
- Fix buffer resizing on X11 (#69).
- Add a set of functions for handling buffer damage (#99).
- Add a `fetch()` function for getting the window contents (#104).
- Bump MSRV to 1.64 (#81).

# 0.2.1

* Bump `windows-sys` to 0.48
- Bump `windows-sys` to 0.48

# 0.2.0

* Add support for Redox/Orbital.
* Add support for BSD distributions.
* Ported Windows backend from `winapi` to `windows-sys`.
* **Breaking:** Take a reference to a window instead of owning the window.
* Add a `from_raw` function for directly using raw handles.
* Improvements for Wayland support.
* Support for HiDPI on macOS.
* **Breaking:** Add feature flags for `x11` and `wayland` backends.
* Use static dispatch instead of dynamic dispatch for the backends.
* Add `libxcb` support to the X11 backend.
* Use X11 MIT-SHM extension, if available.
- Add support for Redox/Orbital.
- Add support for BSD distributions.
- Ported Windows backend from `winapi` to `windows-sys`.
- **Breaking:** Take a reference to a window instead of owning the window.
- Add a `from_raw` function for directly using raw handles.
- Improvements for Wayland support.
- Support for HiDPI on macOS.
- **Breaking:** Add feature flags for `x11` and `wayland` backends.
- Use static dispatch instead of dynamic dispatch for the backends.
- Add `libxcb` support to the X11 backend.
- Use X11 MIT-SHM extension, if available.

# 0.1.1

* Added WASM support (Thanks to [Liamolucko](https://github.com/Liamolucko)!)
* CALayer is now used for Mac OS backend, which is more flexible about what happens in the windowing library (Thanks to [lunixbochs](https://github.com/lunixbochs)!)
- Added WASM support (Thanks to [Liamolucko](https://github.com/Liamolucko)!)
- CALayer is now used for Mac OS backend, which is more flexible about what happens in the windowing library (Thanks to [lunixbochs](https://github.com/lunixbochs)!)

# 0.1.0

Expand Down
18 changes: 18 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ x11-dlopen = ["tiny-xlib/dlopen", "x11rb/dl-libxcb"]
log = "0.4.17"
raw_window_handle = { package = "raw-window-handle", version = "0.6", features = ["std"] }

[target.'cfg(target_os = "android")'.dependencies]
bytemuck = "1.12.3"
ndk = "0.9.0"

[target.'cfg(all(unix, not(any(target_vendor = "apple", target_os = "android", target_os = "redox"))))'.dependencies]
as-raw-xcb-connection = { version = "1.0.0", optional = true }
bytemuck = { version = "1.12.3", optional = true }
Expand Down Expand Up @@ -89,6 +93,10 @@ criterion = { version = "0.4.0", default-features = false, features = ["cargo_be
web-time = "1.0.0"
winit = "0.30.0"

[target.'cfg(target_os = "android")'.dev-dependencies]
winit = { version = "0.30.0", features = ["android-native-activity"] }
android-activity = "0.6"

[dev-dependencies.image]
version = "0.25.0"
# Disable rayon on web
Expand All @@ -110,6 +118,16 @@ members = [
"run-wasm",
]

[[example]]
# Run with `cargo apk r --example winit_android`
name = "winit_android"
crate-type = ["cdylib"]

[[example]]
# Run with `cargo apk r --example winit_multithread_android`
name = "winit_multithread_android"
crate-type = ["cdylib"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
Expand Down
66 changes: 36 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
Overview
==
# Softbuffer

Enables software rendering via drawing an image straight to a window.

Softbuffer integrates with the [`raw-window-handle`](https://crates.io/crates/raw-window-handle) crate
to allow writing pixels to a window in a cross-platform way while using the very high quality dedicated window management
libraries that are available in the Rust ecosystem.

Alternatives
==
## Alternatives

[minifb](https://crates.io/crates/minifb) also allows putting a 2D buffer/image on a window in a platform-independent way. Minifb's approach to doing window management itself, however, is problematic
code duplication. We already have very high quality libraries for this in the Rust ecosystem
Expand All @@ -24,27 +22,27 @@
hardware acceleration (e.g. VMs, older computers, computers with misconfigured drivers). Softbuffer should be used over
pixels when its GPU-accelerated post-processing effects are not needed.

License & Credits
==
## License & Credits

This library is dual-licensed under MIT or Apache-2.0, just like minifb and rust. Significant portions of code were taken
from the minifb library to do platform-specific work.

Platform support:
==
## Platform support:

Some, but not all, platforms supported in [raw-window-handle](https://crates.io/crates/raw-window-handle) are supported
by Softbuffer. Pull requests are welcome to add new platforms! **Nonetheless, all major desktop platforms that winit uses
on desktop are supported.**

For now, the priority for new platforms is:
1) to have at least one platform on each OS working (e.g. one of Win32 or WinRT, or one of Xlib, Xcb, and Wayland) and
2) for that one platform on each OS to be the one that winit uses.

1. to have at least one platform on each OS working (e.g. one of Win32 or WinRT, or one of Xlib, Xcb, and Wayland) and
2. for that one platform on each OS to be the one that winit uses.

(PRs will be accepted for any platform, even if it does not follow the above priority.)

| Platform ||
|-----------|--|
|Android NDK||
|Android NDK||
| AppKit |✅|
| Orbital |✅|
| UIKit |✅|
Expand All @@ -59,13 +57,16 @@
❔: Immature\
❌: Absent

WebAssembly
-----------
## WebAssembly

To run an example with the web backend: `cargo run-wasm --example winit`

Example
==
## Android

To run the Android-specific example on an Android phone: `cargo apk r --example winit_android` or `cargo apk r --example winit_multithread_android`.

## Example

```rust,no_run
use std::num::NonZeroU32;
use std::rc::Rc;
Expand All @@ -75,25 +76,31 @@

#[path = "../examples/utils/winit_app.rs"]
mod winit_app;

Check failure on line 79 in README.md

View workflow job for this annotation

GitHub Actions / Tests (nightly, x86_64-pc-windows-msvc, windows-latest)

couldn't read src\..\..\examples\utils\winit_app.rs: The system cannot find the path specified. (os error 3)

Check failure on line 79 in README.md

View workflow job for this annotation

GitHub Actions / Tests (nightly, x86_64-unknown-linux-gnu, ubuntu-latest)

couldn't read src/../../examples/utils/winit_app.rs: No such file or directory (os error 2)

Check failure on line 79 in README.md

View workflow job for this annotation

GitHub Actions / Tests (nightly, aarch64-apple-darwin, macos-latest)

couldn't read src/../../examples/utils/winit_app.rs: No such file or directory (os error 2)
fn main() {
let event_loop = EventLoop::new().unwrap();

let mut app = winit_app::WinitAppBuilder::with_init(|elwt| {
let window = {
let window = elwt.create_window(Window::default_attributes());
Rc::new(window.unwrap())
};
let context = softbuffer::Context::new(window.clone()).unwrap();
let surface = softbuffer::Surface::new(&context, window.clone()).unwrap();

(window, surface)
}).with_event_handler(|state, event, elwt| {
let (window, surface) = state;
let mut app = winit_app::WinitAppBuilder::with_init(
|elwt| {
let window = {
let window = elwt.create_window(Window::default_attributes());
Rc::new(window.unwrap())
};
let context = softbuffer::Context::new(window.clone()).unwrap();

(window, context)
},
|_elwt, (window, context)| softbuffer::Surface::new(context, window.clone()).unwrap(),
)
.with_event_handler(|(window, _context), surface, event, elwt| {
elwt.set_control_flow(ControlFlow::Wait);

match event {
Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => {
let Some(surface) = surface else {
eprintln!("RedrawRequested fired before Resumed or after Suspended");
return;
};
let (width, height) = {
let size = window.inner_size();
(size.width, size.height)
Expand Down Expand Up @@ -132,8 +139,8 @@
}
```

MSRV Policy
==
## MSRV Policy

This crate's Minimum Supported Rust Version (MSRV) is **1.70**. Changes to
the MSRV will be accompanied by a minor version bump.

Expand All @@ -157,7 +164,6 @@

[`rust-windowing`]: https://github.com/rust-windowing

Changelog
---------
## Changelog

See the [changelog](CHANGELOG.md) for a list of this package's versions and the changes made in each version.
34 changes: 24 additions & 10 deletions examples/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,23 @@ fn main() {
let event_loop = EventLoop::new().unwrap();
let start = Instant::now();

let app = winit_app::WinitAppBuilder::with_init(|event_loop| {
let window = winit_app::make_window(event_loop, |w| w);
let app = winit_app::WinitAppBuilder::with_init(
|event_loop| {
let window = winit_app::make_window(event_loop, |w| w);

let context = softbuffer::Context::new(window.clone()).unwrap();
let surface = softbuffer::Surface::new(&context, window.clone()).unwrap();
let context = softbuffer::Context::new(window.clone()).unwrap();

let old_size = (0, 0);
let frames = pre_render_frames(0, 0);
let old_size = (0, 0);
let frames = pre_render_frames(0, 0);

(window, surface, old_size, frames)
})
.with_event_handler(move |state, event, elwt| {
let (window, surface, old_size, frames) = state;
(window, context, old_size, frames)
},
|_elwft, (window, context, _old_size, _frames)| {
softbuffer::Surface::new(context, window.clone()).unwrap()
},
)
.with_event_handler(move |state, surface, event, elwt| {
let (window, _context, old_size, frames) = state;

elwt.set_control_flow(ControlFlow::Poll);

Expand All @@ -35,6 +39,11 @@ fn main() {
window_id,
event: WindowEvent::Resized(size),
} if window_id == window.id() => {
let Some(surface) = surface else {
eprintln!("Resized fired before Resumed or after Suspended");
return;
};

if let (Some(width), Some(height)) =
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
{
Expand All @@ -45,6 +54,11 @@ fn main() {
window_id,
event: WindowEvent::RedrawRequested,
} if window_id == window.id() => {
let Some(surface) = surface else {
eprintln!("RedrawRequested fired before Resumed or after Suspended");
return;
};

let size = window.inner_size();
if let (Some(width), Some(height)) =
(NonZeroU32::new(size.width), NonZeroU32::new(size.height))
Expand Down
49 changes: 29 additions & 20 deletions examples/fruit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,44 @@ fn main() {

let event_loop = EventLoop::new().unwrap();

let app = winit_app::WinitAppBuilder::with_init(move |elwt| {
let window = winit_app::make_window(elwt, |w| {
w.with_inner_size(winit::dpi::PhysicalSize::new(width, height))
});
let app = winit_app::WinitAppBuilder::with_init(
move |elwt| {
let window = winit_app::make_window(elwt, |w| {
w.with_inner_size(winit::dpi::PhysicalSize::new(width, height))
});

let context = softbuffer::Context::new(window.clone()).unwrap();
let mut surface = softbuffer::Surface::new(&context, window.clone()).unwrap();
let context = softbuffer::Context::new(window.clone()).unwrap();

// Intentionally only set the size of the surface once, at creation.
// This is needed if the window chooses to ignore the size we passed in above, and for the
// platforms softbuffer supports that don't yet extract the size from the window.
surface
.resize(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
)
.unwrap();

(window, surface)
})
.with_event_handler(move |state, event, elwt| {
let (window, surface) = state;
(window, context)
},
move |_elwt, (window, context)| {
let mut surface = softbuffer::Surface::new(context, window.clone()).unwrap();
// Intentionally only set the size of the surface once, at creation.
// This is needed if the window chooses to ignore the size we passed in above, and for the
// platforms softbuffer supports that don't yet extract the size from the window.
surface
.resize(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
)
.unwrap();
surface
},
)
.with_event_handler(move |state, surface, event, elwt| {
let (window, _context) = state;
elwt.set_control_flow(ControlFlow::Wait);

match event {
Event::WindowEvent {
window_id,
event: WindowEvent::RedrawRequested,
} if window_id == window.id() => {
let Some(surface) = surface else {
eprintln!("RedrawRequested fired before Resumed or after Suspended");
return;
};

let mut buffer = surface.buffer_mut().unwrap();
let width = fruit.width() as usize;
for (x, y, pixel) in fruit.pixels() {
Expand Down
Loading
Loading