1use std::collections::HashMap;
5use std::time::Instant;
6
7use crate::assets::Assets;
8use crate::audio::AudioOut;
9use crate::angle::Angle;
10use crate::gfx::Gfx;
11use crate::host::{Game, Host, LoadOptions, Stop};
12use crate::net::Net;
13use crate::storage::Storage;
14
15pub struct Session {
16 pub name: String,
18 pub wasm: Vec<u8>,
20 pub assets: Assets,
21 pub params: HashMap<String, String>,
22 pub allow_net: bool,
23 pub storage: Storage,
24 pub load: LoadOptions,
25 pub gl_lib: Option<std::path::PathBuf>,
27 pub gl_software: bool,
29}
30
31impl Session {
32 pub fn uses_gl(&self) -> bool {
34 crate::host::imports_module(&self.wasm, "gasm:gl", self.load.allow_precompiled)
35 }
36
37 pub fn open_gl(&self, window: Option<crate::angle::NativeWindow>, size: (u32, u32)) -> Result<Angle, String> {
39 let dir = crate::angle::find(self.gl_lib.as_deref())?;
40 let open = |software| match window {
41 Some(w) => Angle::window(&dir, w, software),
42 None => Angle::offscreen(&dir, size.0, size.1, software),
43 };
44 match open(self.gl_software) {
45 Err(e) if !self.gl_software => {
47 eprintln!("[gasm] gl: {e}; trying SwiftShader (software)");
48 open(true)
49 }
50 r => r,
51 }
52 }
53
54 pub fn start(self, audio: Option<Box<dyn AudioOut>>, gfx: Gfx, gl: Option<Angle>, reproducible: bool, hashing: bool) -> Result<Game, Stop> {
58 let mut host = Host::new(self.assets, self.params, audio, gfx, Net::new(self.allow_net), self.storage);
59 if let Some(a) = gl {
60 eprintln!("[gasm] gl: {}", a.renderer);
61 host.gl.attach(a);
62 }
63 if reproducible {
64 host.set_reproducible();
65 }
66 host.hashing = hashing;
67 let t0 = Instant::now();
68 let game = Game::load(&self.wasm, host, self.load)?;
69 eprintln!("[gasm] loaded {} in {:.0} ms", self.name, t0.elapsed().as_secs_f64() * 1000.0);
70 Ok(game)
71 }
72}