From bb898d78dece4d21cf9f3ce2b27aacd69b14d1e5 Mon Sep 17 00:00:00 2001 From: Jay Oster Date: Tue, 19 Nov 2019 19:58:21 -0800 Subject: [PATCH] Add minimal-sdl2 example (#48) --- Cargo.lock | 35 ++++++++++ Cargo.toml | 7 ++ examples/minimal-sdl2/README.md | 17 +++++ examples/minimal-sdl2/main.rs | 120 ++++++++++++++++++++++++++++++++ img/minimal-sdl2.png | Bin 0 -> 1421 bytes 5 files changed, 179 insertions(+) create mode 100644 examples/minimal-sdl2/README.md create mode 100644 examples/minimal-sdl2/main.rs create mode 100755 img/minimal-sdl2.png diff --git a/Cargo.lock b/Cargo.lock index 8972723..fc406cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,6 +91,17 @@ name = "base-x" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "beryllium" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fermium 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "phantom-fields 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "raw-window-handle 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "1.2.1" @@ -245,6 +256,16 @@ dependencies = [ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fermium" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fnv" version = "1.0.6" @@ -765,10 +786,21 @@ name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "phantom-fields" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pixels" version = "0.0.2" dependencies = [ + "beryllium 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1514,6 +1546,7 @@ dependencies = [ "checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base-x 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" +"checksum beryllium 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c821518d537a3ac0299396c4cfe84a877c0d83c494fd5c4310ec87873711d12" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" "checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" @@ -1535,6 +1568,7 @@ dependencies = [ "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +"checksum fermium 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6989d270a6fa93ffa2c4c1c7c2ef56c8315d2aa099e000e413665808a4c68050" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -1590,6 +1624,7 @@ dependencies = [ "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum pcx 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1b00b062973776578e7863f8395f86e821760d827384f1ad9371d0893c87481a" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +"checksum phantom-fields 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cc7d5c2ec53ed64f6d636d44717906952de3d7930178b680b272c62fdd7e7968" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" diff --git a/Cargo.toml b/Cargo.toml index c08ca85..775e942 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ wgpu = "0.4" # These are only used by the examples, and enabled with features # See: https://github.com/rust-lang/cargo/issues/1982 +beryllium = { version = " 0.1", optional = true } byteorder = { version = "1.3", optional = true } env_logger = { version = "0.7", optional = true } getrandom = { version = "0.1", optional = true } @@ -50,6 +51,10 @@ required-features = ["conway"] name = "invaders" required-features = ["invaders"] +[[example]] +name = "minimal-sdl2" +required-features = ["minimal-sdl2"] + [[example]] name = "minimal-winit" required-features = ["minimal-winit"] @@ -58,10 +63,12 @@ required-features = ["minimal-winit"] default = [] log-deps = ["env_logger", "log"] random-deps = ["byteorder", "getrandom", "randomize"] +sdl2-deps = ["beryllium"] winit-deps = ["winit", "winit_input_helper"] conway = ["line_drawing", "log-deps", "random-deps", "winit-deps"] invaders = ["gilrs", "log-deps", "random-deps", "simple-invaders", "winit-deps"] +minimal-sdl2 = ["log-deps", "sdl2-deps"] minimal-winit = ["log-deps", "winit-deps"] [workspace] diff --git a/examples/minimal-sdl2/README.md b/examples/minimal-sdl2/README.md new file mode 100644 index 0000000..aac54d4 --- /dev/null +++ b/examples/minimal-sdl2/README.md @@ -0,0 +1,17 @@ +# Hello Pixels + +![Hello Pixels](../../img/minimal-sdl2.png) + +Minimal example with SDL2 using `beryllium`. + +## Running + +```bash +cargo run --release --example minimal-sdl2 --features minimal-sdl2 +``` + +## About + +This example demonstrates the absolute minimum for creating an SDL2 window and pixel buffer. It animates a purple box moving on a blue background, just for _something_ interesting to display. + +The example currently does not run on macOS. See [#47](https://github.com/parasyte/pixels/issues/47) for details. diff --git a/examples/minimal-sdl2/main.rs b/examples/minimal-sdl2/main.rs new file mode 100644 index 0000000..0cd9f92 --- /dev/null +++ b/examples/minimal-sdl2/main.rs @@ -0,0 +1,120 @@ +#![deny(clippy::all)] +#![forbid(unsafe_code)] +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +use beryllium::*; +use pixels::{wgpu::Surface, Pixels, SurfaceTexture}; + +const WIDTH: u32 = 320; +const HEIGHT: u32 = 240; +const BOX_SIZE: i16 = 64; + +/// Representation of the application state. In this example, a box will bounce around the screen. +struct World { + box_x: i16, + box_y: i16, + velocity_x: i16, + velocity_y: i16, +} + +fn main() -> Result<(), String> { + env_logger::init(); + let sdl = beryllium::init()?; + let window = sdl.create_window( + "Hello Pixels", + WINDOW_POSITION_CENTERED, + WINDOW_POSITION_CENTERED, + WIDTH as i32, + HEIGHT as i32, + WindowFlags::default(), + )?; + window.set_minimum_size(WIDTH as i32, HEIGHT as i32); + window.set_resizable(true); + + let mut pixels = { + let surface = Surface::create(&window); + let surface_texture = SurfaceTexture::new(WIDTH, HEIGHT, surface); + Pixels::new(WIDTH, HEIGHT, surface_texture).map_err(|e| format!("{:?}", e))? + }; + let mut world = World::new(); + + 'game_loop: loop { + while let Some(event) = sdl.poll_event() { + match event { + // Close events + Event::Quit { .. } => break 'game_loop, + Event::Keyboard { + key_info: + KeyInfo { + keycode: Some(key), .. + }, + .. + } if key == Keycode::Escape => break 'game_loop, + + // Resize the window + Event::WindowSizeChanged { width, height, .. } => { + pixels.resize(width as u32, height as u32) + } + + _ => (), + } + } + + // Update internal state + world.update(); + + // Draw the current frame + world.draw(pixels.get_frame()); + pixels.render(); + } + + Ok(()) +} + +impl World { + /// Create a new `World` instance that can draw a moving box. + fn new() -> Self { + Self { + box_x: 24, + box_y: 16, + velocity_x: 1, + velocity_y: 1, + } + } + + /// Update the `World` internal state; bounce the box around the screen. + fn update(&mut self) { + if self.box_x <= 0 || self.box_x + BOX_SIZE - 1 >= WIDTH as i16 { + self.velocity_x *= -1; + } + if self.box_y <= 0 || self.box_y + BOX_SIZE - 1 >= HEIGHT as i16 { + self.velocity_y *= -1; + } + + self.box_x += self.velocity_x; + self.box_y += self.velocity_y; + } + + /// Draw the `World` state to the frame buffer. + /// + /// Assumes the default texture format: [`wgpu::TextureFormat::Rgba8UnormSrgb`] + fn draw(&self, frame: &mut [u8]) { + for (i, pixel) in frame.chunks_exact_mut(4).enumerate() { + let x = (i % WIDTH as usize) as i16; + let y = (i / WIDTH as usize) as i16; + + let inside_the_box = x >= self.box_x + && x < self.box_x + BOX_SIZE + && y >= self.box_y + && y < self.box_y + BOX_SIZE; + + let rgba = if inside_the_box { + [0x5e, 0x48, 0xe8, 0xff] + } else { + [0x48, 0xb2, 0xe8, 0xff] + }; + + pixel.copy_from_slice(&rgba); + } + } +} diff --git a/img/minimal-sdl2.png b/img/minimal-sdl2.png new file mode 100755 index 0000000000000000000000000000000000000000..4bba0116e6a6ad4606887a1bed91e9d02225a976 GIT binary patch literal 1421 zcmchXiBnTo6o((R9m0|UM5O9qOGJVTRaB%C=?H0PVXPP+m4Zb`!B|=?2vksE7zD}^ zkN|=rAO#6aWJd@D2qZuw`x+Ed)ToG%m+b|!K*H-wr~U(-PVd}v=FYj_Ip=rg&fE;5 z_t$9SoyGtFpuIc^z5rl=N6Z|x1&Kh;+4?{e@f(td!#=Eo19p!c#!kQYV6pZN4)!n% zPfgGEar!5xW^_7TePiqBB!6^rc5I5@(#dV<;8ZahKoDee2GkmjO0DT)bC#BtkjkT@ zqul<%rwgyrOW7G^J(=a*)XJ{xYS!G`Gl>{{DHMvu;JxM%7;dKkIGO;aAUOaI7SM12 z?ju7KhdVGYc=O|}mhimhOLrT7DXqIw!I+v7NWj%n=Fs01k_5B5dlM=;f4W;2l>d7` zK~X@_Z3!q6>eq`3Zh!R%+mBl6m7ae(hej;O^1GK_Kf`Q((t^|XqO`*>Vl=_~V(k}yty0S6a;a3()7Rh29qj4l*48yHFE1;VO3#+J z=RM!<^Zp!z%wZJi84wKsW@Nn?)SRpi2Y@ZfUIcei+=BS2Cff2_pil107zyvR_3&__ zKSH~Fm~5Da8s-<;mpHyK7~cD7CbRHM6W`at6qn-4a6jBiSQr=5Y&Ko%QrI8WjItBF z0t4^Q)XmM!`^cRd>gz9GebvTRuGbY3tZK^5F@$s?%HsGAVM!-{tk~@0A1Nl=**=%Z zH#RB;sdo;h9u4JQ81c_y#xF6#5@jShixNA~Xj2<*oW!13*S|`kG#wCB2 zNnE2I{dPF|Apc1)#*|l^v>)lsGgP?ScH4}!dYcwf>{1UOD+!Fm2#5TtCrZX7Cf3j- zv8bt9{aEZcYy~-y{U_X3+T`m!P^RF(sqsiLYUD$&Y z#y7vO*dCQ27*a74)$;K(C*iGIH`fKye50=GkQMhOem5`k5YMF3^?>UeXvnrsacb<7 z#7*ZTQL1M;!^G#>i!m__ab-8{!Ig+u;^~hsV>{zc>>J;|&076X$-mAS?nukoMCau2 zv@ykUvuk~dj_3qZi`RBrz75$kZ%6|tuX`#1o;O< z0M!4D;obC-Qikl}7eWvrh%~*5|MtLrZOJD6+o_B1646T26V{5e@&WC6{b%Fl;Z113 Hhur)NtT44= literal 0 HcmV?d00001