This commit is contained in:
Skye 2023-01-10 13:12:46 +09:00
commit 1216ed0d09
Signed by: me
GPG key ID: 0104BC05F41B77B8
13 changed files with 1021 additions and 0 deletions

6
.cargo/config.toml Normal file
View file

@ -0,0 +1,6 @@
[unstable]
build-std = ["core", "compiler_builtins", "alloc"]
build-std-features = ["compiler-builtins-mem"]
[build]
target = "aarch64-nintendo-switch-freestanding"

1
.envrc Normal file
View file

@ -0,0 +1 @@
use flake

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
target/
.direnv/

231
Cargo.lock generated Normal file
View file

@ -0,0 +1,231 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ab_glyph_rasterizer"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6"
dependencies = [
"libm",
]
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "convert_case"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "font8x8"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e63201c624b8c8883921b1a1accc8916c4fa9dbfb15d122b26e4dde945b86bbf"
[[package]]
name = "itoa"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]]
name = "libm"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
[[package]]
name = "linked_list_allocator"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
[[package]]
name = "logpacket"
version = "0.1.0"
source = "git+https://github.com/aarch64-switch-rs/logpacket#d807c993fb4578e3809d91e3484c7d97f59eb3db"
[[package]]
name = "nx"
version = "0.1.0"
source = "git+https://github.com/aarch64-switch-rs/nx#31f4590cac1776a4731380c29bcbb972591b5bba"
dependencies = [
"arrayvec",
"linked_list_allocator",
"logpacket",
"paste",
"static_assertions",
]
[[package]]
name = "owned_ttf_parser"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05e6affeb1632d6ff6a23d2cd40ffed138e82f1532571a26f527c8a284bb2fbb"
dependencies = [
"ttf-parser",
]
[[package]]
name = "paste"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
[[package]]
name = "proc-macro2"
version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
[[package]]
name = "rusttype"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ff8374aa04134254b7995b63ad3dc41c7f7236f69528b28553da7d72efaa967"
dependencies = [
"ab_glyph_rasterizer",
"libm",
"owned_ttf_parser",
]
[[package]]
name = "ryu"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "ttf-parser"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]]
name = "ui2d"
version = "0.1.0"
dependencies = [
"font8x8",
"libm",
"nx",
"rusttype",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-segmentation"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
[[package]]
name = "uwurandom-nx"
version = "0.1.0"
dependencies = [
"nx",
"rand_core",
"ui2d",
"uwurandom-rs",
]
[[package]]
name = "uwurandom-proc-macros"
version = "0.1.0"
source = "git+https://git.skye.vg/me/uwurandom-rs#9b7344cadb7d1a73f5dec92ee2a77bad2a1e1d76"
dependencies = [
"convert_case",
"quote",
"serde",
"serde_json",
"syn",
]
[[package]]
name = "uwurandom-rs"
version = "0.1.0"
source = "git+https://git.skye.vg/me/uwurandom-rs#9b7344cadb7d1a73f5dec92ee2a77bad2a1e1d76"
dependencies = [
"rand_core",
"uwurandom-proc-macros",
]

19
Cargo.toml Normal file
View file

@ -0,0 +1,19 @@
[package]
name = "uwurandom-nx"
authors = ["aarch64-switch-rs authors"]
version = "0.1.0"
edition = "2021"
[dependencies]
nx = { git = "https://github.com/aarch64-switch-rs/nx", features=["input", "rand"] }
rand_core = "0.6.4"
ui2d = { path = "./ui2d" }
uwurandom-rs = { git = "https://git.skye.vg/me/uwurandom-rs" }
# For help / more information, see https://github.com/aarch64-switch-rs/cargo-nx/wiki
[package.metadata.nx.nro.nacp]
default_name = "uwurandom-nx"
default_author = "skyevg"
version = "0.1.0"
application_id = "0x010018160C3AFA2D"

BIN
Inter-Regular.ttf Normal file

Binary file not shown.

94
flake.lock Normal file
View file

@ -0,0 +1,94 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1672525397,
"narHash": "sha256-WASDnyxHKWVrEe0dIzkpH+jzKlCKAk0husv0f/9pyxg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "8ba56d7c0d7490680f2d51ba46a141eca7c46afa",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1665296151,
"narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"rust-overlay": "rust-overlay"
}
},
"rust-overlay": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1672712534,
"narHash": "sha256-8S0DdMPcbITnlOu0uA81mTo3hgX84wK8S9wS34HEFY4=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "69fb7bf0a8c40e6c4c197fa1816773774c8ac59f",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

25
flake.nix Normal file
View file

@ -0,0 +1,25 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs { inherit system overlays; };
in
with pkgs; {
devShells.default = mkShell {
buildInputs = [
(rust-bin.selectLatestNightlyWith (toolchain:
toolchain.default.override {
extensions = [ "rust-src" ];
targets = [ "thumbv6m-none-eabi" ];
}))
];
};
});
}

192
src/main.rs Normal file
View file

@ -0,0 +1,192 @@
#![no_std]
#![no_main]
extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
extern crate nx;
use nx::diag::abort;
use nx::diag::log::lm::LmLogger;
use nx::gpu;
use nx::input;
use nx::rand::RandomGenerator;
use nx::result::*;
use nx::service::hid;
use nx::svc;
use nx::util;
use rand_core::RngCore;
use uwurandom_rs::StateMachine;
use core::panic;
extern crate ui2d;
#[no_mangle]
pub fn initialize_heap(hbl_heap: util::PointerAndSize) -> util::PointerAndSize {
if hbl_heap.is_valid() {
hbl_heap
} else {
let heap_size: usize = 0x10000000;
let heap_address = svc::set_heap_size(heap_size).unwrap();
util::PointerAndSize::new(heap_address, heap_size)
}
}
pub struct Square {
x: i32,
y: i32,
size: i32,
x_incr: i32,
y_incr: i32,
x_mult: i32,
y_mult: i32,
color: ui2d::RGBA8,
}
impl Square {
pub fn new(x: i32, y: i32, size: i32, color: ui2d::RGBA8) -> Self {
Self {
x: x,
y: y,
size: size,
x_incr: 1,
y_incr: 1,
x_mult: 1,
y_mult: 1,
color: color,
}
}
pub fn handle_render(&mut self, surface: &mut ui2d::SurfaceEx) {
surface.draw(self.x, self.y, self.size, self.size, self.color, false);
self.x += self.x_incr * self.x_mult;
self.y += self.y_incr * self.y_mult;
if self.x <= 0 {
if self.x_incr < 0 {
self.x_incr -= 1;
self.x_incr = -self.x_incr;
}
self.x += self.x_incr * self.x_mult;
self.x_mult += 1;
} else if (self.x + self.size) as u32 >= surface.get_width() {
if self.x_incr > 0 {
self.x_incr += 1;
self.x_incr = -self.x_incr;
}
self.x += self.x_incr * self.x_mult;
self.x_mult += 1;
}
if self.y <= 0 {
if self.y_incr < 0 {
self.y_incr -= 1;
self.y_incr = -self.y_incr;
}
self.y += self.y_incr * self.y_mult;
self.y_mult += 1;
} else if (self.y + self.size) as u32 >= surface.get_height() {
if self.y_incr > 0 {
self.y_incr += 1;
self.y_incr = -self.y_incr;
}
self.y += self.y_incr * self.y_mult;
self.y_mult += 1;
}
}
}
struct NxRngWrap(nx::rand::SplCsrngGenerator);
impl RngCore for NxRngWrap {
fn next_u32(&mut self) -> u32 {
rand_core::impls::next_u32_via_fill(self)
}
fn next_u64(&mut self) -> u64 {
rand_core::impls::next_u64_via_fill(self)
}
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.0.random_bytes(dest.as_ptr() as _, dest.len()).unwrap()
}
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), rand_core::Error> {
Ok(self.fill_bytes(dest))
}
}
impl NxRngWrap {
fn new() -> Self {
Self(nx::rand::SplCsrngGenerator::new().unwrap())
}
}
#[no_mangle]
pub fn main() -> Result<()> {
let mut gpu_ctx = gpu::Context::new(
gpu::NvDrvServiceKind::Applet,
gpu::ViServiceKind::System,
0x800000,
)?;
let supported_style_tags = hid::NpadStyleTag::Handheld();
let supported_npad_ids = [hid::NpadIdType::Handheld];
let input_ctx = input::Context::new(supported_style_tags, &supported_npad_ids)?;
let color_fmt = gpu::ColorFormat::A8B8G8R8;
let c_white = ui2d::RGBA8::new_rgb(0xFF, 0xFF, 0xFF);
let c_black = ui2d::RGBA8::new_rgb(0, 0, 0);
let font_data = include_bytes!("../Inter-Regular.ttf");
let font = ui2d::Font::try_from_bytes(font_data as &[u8]).unwrap();
let mut surface = ui2d::SurfaceEx::from(gpu_ctx.create_stray_layer_surface(
"Default",
2,
color_fmt,
gpu::PixelFormat::RGBA_8888,
gpu::Layout::BlockLinear,
)?);
let mut rng = NxRngWrap::new();
let mut uwurandom = StateMachine::new(&mut rng);
let mut result = String::from("Press + to exit\n");
loop {
let mut p_handheld = input_ctx.get_player(hid::NpadIdType::Handheld);
let buttons_down = p_handheld.get_buttons_down();
if buttons_down.contains(hid::NpadButton::A()) {
let (new_state, generated) = uwurandom.generate(&mut rng);
uwurandom = new_state;
result.push(generated);
if result.lines().last().unwrap().len() > 100 {
result.push('\n');
}
} else if buttons_down.contains(hid::NpadButton::Plus()) {
// Exit if Plus/+ is pressed.
break;
}
surface.start()?;
surface.clear(c_white);
surface.draw_font_text(&font, result.clone(), c_black, 25.0, 10, 10, true);
// surface.draw_bitmap_text(result.clone(), c_black, 2, 10, 250, true);
surface.end()?;
}
Ok(())
}
#[panic_handler]
fn panic_handler(info: &panic::PanicInfo) -> ! {
util::simple_panic_handler::<LmLogger>(info, abort::AbortLevel::FatalThrow())
}

3
ui2d/.cargo/config.toml Normal file
View file

@ -0,0 +1,3 @@
[unstable]
build-std = ["core", "compiler_builtins", "alloc"]
build-std-features = ["compiler-builtins-mem"]

101
ui2d/Cargo.lock generated Normal file
View file

@ -0,0 +1,101 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ab_glyph_rasterizer"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e"
dependencies = [
"libm",
]
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "font8x8"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e63201c624b8c8883921b1a1accc8916c4fa9dbfb15d122b26e4dde945b86bbf"
[[package]]
name = "libm"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db"
[[package]]
name = "linked_list_allocator"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
[[package]]
name = "logpacket"
version = "0.1.0"
source = "git+https://github.com/aarch64-switch-rs/logpacket#d807c993fb4578e3809d91e3484c7d97f59eb3db"
[[package]]
name = "nx"
version = "0.1.0"
source = "git+https://github.com/aarch64-switch-rs/nx#bfa3d790e023acc6dbe07a3ac1f70987e6f62a28"
dependencies = [
"arrayvec",
"linked_list_allocator",
"logpacket",
"paste",
"static_assertions",
]
[[package]]
name = "owned_ttf_parser"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3"
dependencies = [
"ttf-parser",
]
[[package]]
name = "paste"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
[[package]]
name = "rusttype"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59"
dependencies = [
"ab_glyph_rasterizer",
"libm",
"owned_ttf_parser",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "ttf-parser"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc"
[[package]]
name = "ui2d"
version = "0.1.0"
dependencies = [
"font8x8",
"libm",
"nx",
"rusttype",
]

23
ui2d/Cargo.toml Normal file
View file

@ -0,0 +1,23 @@
[package]
name = "ui2d"
version = "0.1.0"
authors = ["XorTroll"]
edition = "2021"
[dependencies]
nx = { git = "https://github.com/aarch64-switch-rs/nx", features = [ "gpu" ] }
[dependencies.font8x8]
version = "0.2"
default-features = false
features = ["unicode"]
[dependencies.rusttype]
version = "0.9.2"
default-features = false
features = ["libm-math"]
[dependencies.libm]
version = "0.2.1"
default-features = false
features = []

324
ui2d/src/lib.rs Normal file
View file

@ -0,0 +1,324 @@
#![no_std]
// Note: quite simple lib made for UI tests to easily render stuff
use nx::result::*;
use nx::gpu;
use nx::arm;
extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
use core::ptr;
use core::mem;
use font8x8::UnicodeFonts;
pub type Font<'a> = rusttype::Font<'a>;
#[derive(Copy, Clone)]
pub struct RGBA8 {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl RGBA8 {
pub const fn new_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Self { r: r, g: g, b: b, a: a }
}
pub const fn new_rgb(r: u8, g: u8, b: u8) -> Self {
Self { r: r, g: g, b: b, a: 0xFF }
}
const fn decode(raw: u32) -> (u8, u8, u8, u8) {
let a = (raw & 0xFF) as u8;
let b = ((raw >> 8) & 0xFF) as u8;
let c = ((raw >> 16) & 0xFF) as u8;
let d = ((raw >> 24) & 0xFF) as u8;
(a, b, c, d)
}
pub const fn from_rgba(raw: u32) -> Self {
let (a, b, g, r) = Self::decode(raw);
Self::new_rgba(r, g, b, a)
}
pub const fn from_abgr(raw: u32) -> Self {
let (r, g, b, a) = Self::decode(raw);
Self::new_rgba(r, g, b, a)
}
const fn encode(a: u8, b: u8, c: u8, d: u8) -> u32 {
(a as u32 & 0xFF) | ((b as u32 & 0xFF) << 8) | ((c as u32 & 0xFF) << 16) | ((d as u32 & 0xFF) << 24)
}
pub const fn encode_rgba(&self) -> u32 {
Self::encode(self.a, self.b, self.g, self.r)
}
pub const fn encode_abgr(&self) -> u32 {
Self::encode(self.r, self.g, self.b, self.a)
}
const fn blend_color_impl(src: u32, dst: u32, alpha: u32) -> u8 {
let one_minus_a = 0xFF - alpha;
((dst * alpha + src * one_minus_a) / 0xFF) as u8
}
pub const fn blend_with(&self, other: Self) -> Self {
let r = Self::blend_color_impl(other.r as u32, self.r as u32, self.a as u32);
let g = Self::blend_color_impl(other.g as u32, self.g as u32, self.a as u32);
let b = Self::blend_color_impl(other.b as u32, self.b as u32, self.a as u32);
Self::new_rgb(r, g, b)
}
}
pub struct SurfaceEx {
gpu_buf: *mut u32,
gpu_buf_size: usize,
linear_buf: *mut u32,
linear_buf_size: usize,
slot: i32,
fences: gpu::MultiFence,
surface_ref: gpu::surface::Surface,
}
impl SurfaceEx {
pub fn from(surface: gpu::surface::Surface) -> Self {
let aligned_width = surface.compute_stride() as usize;
let aligned_height = ((surface.get_height() + 7) & !7) as usize;
let linear_buf_size = aligned_width * aligned_height;
unsafe {
let linear_buf_layout = alloc::alloc::Layout::from_size_align_unchecked(linear_buf_size, 8);
let linear_buf = alloc::alloc::alloc_zeroed(linear_buf_layout);
Self { gpu_buf: ptr::null_mut(), gpu_buf_size: 0, linear_buf: linear_buf as *mut u32, linear_buf_size: linear_buf_size, slot: 0, fences: mem::zeroed(), surface_ref: surface }
}
}
pub fn start(&mut self) -> Result<()> {
let (buf, buf_size, slot, _has_fences, fences) = self.surface_ref.dequeue_buffer(true)?;
self.gpu_buf = buf as *mut u32;
self.gpu_buf_size = buf_size;
self.slot = slot;
self.fences = fences;
self.surface_ref.wait_fences(fences, -1)
}
pub fn get_surface(&mut self) -> &mut gpu::surface::Surface {
&mut self.surface_ref
}
fn convert_buffers_gob_impl(out_gob_buf: *mut u8, in_gob_buf: *mut u8, stride: u32) {
unsafe {
let mut tmp_out_gob_buf_128 = out_gob_buf as *mut u128;
for i in 0..32 {
let y = ((i >> 1) & 0x6) | (i & 0x1);
let x = ((i << 3) & 0x10) | ((i << 1) & 0x20);
let out_gob_buf_128 = tmp_out_gob_buf_128 as *mut u128;
let in_gob_buf_128 = in_gob_buf.offset((y * stride + x) as isize) as *mut u128;
*out_gob_buf_128 = *in_gob_buf_128;
tmp_out_gob_buf_128 = tmp_out_gob_buf_128.offset(1);
}
}
}
fn convert_buffers_impl(out_buf: *mut u8, in_buf: *mut u8, stride: u32, height: u32) {
let block_height_gobs = 1 << gpu::BLOCK_HEIGHT_LOG2;
let block_height_px = 8 << gpu::BLOCK_HEIGHT_LOG2;
let width_blocks = stride >> 6;
let height_blocks = (height + block_height_px - 1) >> (3 + gpu::BLOCK_HEIGHT_LOG2);
let mut tmp_out_buf = out_buf;
for block_y in 0..height_blocks {
for block_x in 0..width_blocks {
for gob_y in 0..block_height_gobs {
unsafe {
let x = block_x * 64;
let y = block_y * block_height_px + gob_y * 8;
if y < height {
let in_gob_buf = in_buf.offset((y * stride + x) as isize);
Self::convert_buffers_gob_impl(tmp_out_buf, in_gob_buf, stride);
}
tmp_out_buf = tmp_out_buf.offset(512);
}
}
}
}
}
pub fn end(&mut self) -> Result<()> {
Self::convert_buffers_impl(self.gpu_buf as *mut u8, self.linear_buf as *mut u8, self.surface_ref.compute_stride(), self.surface_ref.get_height());
arm::cache_flush(self.gpu_buf as *mut u8, self.gpu_buf_size);
self.surface_ref.queue_buffer(self.slot, self.fences)?;
self.surface_ref.wait_vsync_event(-1)
}
pub fn clear(&mut self, color: RGBA8) {
unsafe {
let buf_size_32 = self.linear_buf_size / mem::size_of::<u32>();
for i in 0..buf_size_32 {
let cur = self.linear_buf.offset(i as isize);
*cur = color.encode_abgr();
}
}
}
pub fn draw_single(&mut self, x: i32, y: i32, color: RGBA8, blend: bool) {
unsafe {
let offset = ((self.surface_ref.compute_stride() / mem::size_of::<u32>() as u32) as i32 * y + x) as isize;
let cur = self.linear_buf.offset(offset);
let old_color = RGBA8::from_abgr(*cur);
let new_color = match blend {
true => color.blend_with(old_color),
false => color,
};
*cur = new_color.encode_abgr();
}
}
fn clamp(max: i32, value: i32) -> i32 {
if value < 0 {
return 0;
}
if value > max {
return max;
}
value
}
pub fn get_width(&self) -> u32 {
self.surface_ref.get_width()
}
pub fn get_height(&self) -> u32 {
self.surface_ref.get_height()
}
pub fn get_color_format(&self) -> gpu::ColorFormat {
self.surface_ref.get_color_format()
}
pub fn draw(&mut self, x: i32, y: i32, width: i32, height: i32, color: RGBA8, blend: bool) {
let s_width = self.surface_ref.get_width() as i32;
let s_height = self.surface_ref.get_height() as i32;
let x0 = Self::clamp(s_width, x);
let x1 = Self::clamp(s_width, x + width);
let y0 = Self::clamp(s_height, y);
let y1 = Self::clamp(s_height, y + height);
for y in y0..y1 {
for x in x0..x1 {
self.draw_single(x, y, color, blend);
}
}
}
fn draw_font_text_impl(&mut self, font: &rusttype::Font, text: &str, color: RGBA8, scale: rusttype::Scale, v_metrics: rusttype::VMetrics, x: i32, y: i32, blend: bool) {
let glyphs: Vec<_> = font.layout(&text[..], scale, rusttype::point(0.0, v_metrics.ascent)).collect();
for glyph in &glyphs {
if let Some(bounding_box) = glyph.pixel_bounding_box() {
// Draw the glyph into the image per-pixel by using the draw closure
glyph.draw(|g_x, g_y, g_v| {
let mut pix_color = color;
// Different alpha depending on the pixel
pix_color.a = (g_v * 255.0) as u8;
self.draw_single(x + g_x as i32 + bounding_box.min.x as i32, y + g_y as i32 + bounding_box.min.y as i32, pix_color, blend);
});
}
}
}
pub fn draw_font_text(&mut self, font: &rusttype::Font, text: String, color: RGBA8, size: f32, x: i32, y: i32, blend: bool) {
let scale = rusttype::Scale::uniform(size);
let v_metrics = font.v_metrics(scale);
let mut tmp_y = y;
for semi_text in text.lines() {
self.draw_font_text_impl(font, semi_text, color, scale, v_metrics, x, tmp_y, blend);
tmp_y += v_metrics.ascent as i32;
}
}
pub fn draw_bitmap_text(&mut self, text: String, color: RGBA8, scale: i32, x: i32, y: i32, blend: bool) {
let mut tmp_x = x;
let mut tmp_y = y;
for c in text.chars() {
match c {
'\n' | '\r' => {
tmp_y += 8 * scale;
tmp_x = x;
},
_ => {
if let Some(glyph) = font8x8::BASIC_FONTS.get(c) {
let char_tmp_x = tmp_x;
let char_tmp_y = tmp_y;
for gx in &glyph {
for bit in 0..8 {
match *gx & 1 << bit {
0 => {},
_ => {
self.draw(tmp_x, tmp_y, scale, scale, color, blend);
},
}
tmp_x += scale;
}
tmp_y += scale;
tmp_x = char_tmp_x;
}
tmp_x += 8 * scale;
tmp_y = char_tmp_y;
}
}
}
}
}
}
impl Drop for SurfaceEx {
fn drop(&mut self) {
unsafe {
let linear_buf_layout = alloc::alloc::Layout::from_size_align_unchecked(self.linear_buf_size, 8);
alloc::alloc::dealloc(self.linear_buf as *mut u8, linear_buf_layout);
}
}
}
// Needed by rusttype
pub trait FloatExt {
fn floor(self) -> Self;
fn ceil(self) -> Self;
fn fract(self) -> Self;
fn trunc(self) -> Self;
fn round(self) -> Self;
fn abs(self) -> Self;
}
impl FloatExt for f32 {
#[inline]
fn floor(self) -> Self {
libm::floorf(self)
}
#[inline]
fn ceil(self) -> Self {
libm::ceilf(self)
}
#[inline]
fn fract(self) -> Self {
self - self.trunc()
}
#[inline]
fn trunc(self) -> Self {
libm::truncf(self)
}
#[inline]
fn round(self) -> Self {
libm::roundf(self)
}
#[inline]
fn abs(self) -> Self {
libm::fabsf(self)
}
}