gfx2.rs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use darkfi_serial::{SerialDecodable, SerialEncodable};
  19. use log::debug;
  20. use miniquad::{
  21. conf, window, Backend, Bindings, BlendFactor, BlendState, BlendValue, BufferId, BufferLayout,
  22. BufferSource, BufferType, BufferUsage, Equation, EventHandler, KeyCode, KeyMods, MouseButton,
  23. PassAction, Pipeline, PipelineParams, RenderingBackend, ShaderMeta, ShaderSource, TextureId,
  24. TouchPhase, UniformDesc, UniformType, VertexAttribute, VertexFormat,
  25. };
  26. use std::{
  27. collections::HashMap,
  28. sync::{mpsc, Arc, Mutex as SyncMutex},
  29. time::{Duration, Instant},
  30. };
  31. use crate::{
  32. app::AsyncRuntime,
  33. error::{Error, Result},
  34. pubsub::{Publisher, PublisherPtr, Subscription, SubscriptionId},
  35. shader,
  36. util::ansi_texture,
  37. };
  38. // This is very noisy so suppress output by default
  39. const DEBUG_RENDER: bool = false;
  40. #[derive(Debug, SerialEncodable, SerialDecodable)]
  41. #[repr(C)]
  42. pub struct Vertex {
  43. pub pos: [f32; 2],
  44. pub color: [f32; 4],
  45. pub uv: [f32; 2],
  46. }
  47. impl Vertex {
  48. pub fn pos(&self) -> Point {
  49. self.pos.into()
  50. }
  51. pub fn set_pos(&mut self, pos: &Point) {
  52. self.pos = pos.as_arr();
  53. }
  54. }
  55. pub struct Point {
  56. pub x: f32,
  57. pub y: f32,
  58. }
  59. impl Point {
  60. pub fn unpack(&self) -> (f32, f32) {
  61. (self.x, self.y)
  62. }
  63. pub fn as_arr(&self) -> [f32; 2] {
  64. [self.x, self.y]
  65. }
  66. pub fn offset(&self, off_x: f32, off_y: f32) -> Self {
  67. Self { x: self.x + off_x, y: self.y + off_y }
  68. }
  69. pub fn to_rect(&self, w: f32, h: f32) -> Rectangle {
  70. Rectangle { x: self.x, y: self.y, w, h }
  71. }
  72. }
  73. impl From<[f32; 2]> for Point {
  74. fn from(pos: [f32; 2]) -> Self {
  75. Self { x: pos[0], y: pos[1] }
  76. }
  77. }
  78. #[derive(Debug, Clone)]
  79. pub struct Rectangle {
  80. pub x: f32,
  81. pub y: f32,
  82. pub w: f32,
  83. pub h: f32,
  84. }
  85. impl Rectangle {
  86. pub fn new(x: f32, y: f32, w: f32, h: f32) -> Self {
  87. Self { x, y, w, h }
  88. }
  89. pub fn zero() -> Self {
  90. Self { x: 0., y: 0., w: 0., h: 0. }
  91. }
  92. pub fn from_array(arr: [f32; 4]) -> Self {
  93. Self { x: arr[0], y: arr[1], w: arr[2], h: arr[3] }
  94. }
  95. pub fn clip(&self, other: &Self) -> Option<Self> {
  96. if other.x + other.w < self.x ||
  97. other.x > self.x + self.w ||
  98. other.y + other.h < self.y ||
  99. other.y > self.y + self.h
  100. {
  101. return None
  102. }
  103. let mut clipped = other.clone();
  104. if clipped.x < self.x {
  105. clipped.x = self.x;
  106. clipped.w = other.x + other.w - clipped.x;
  107. }
  108. if clipped.y < self.y {
  109. clipped.y = self.y;
  110. clipped.h = other.y + other.h - clipped.y;
  111. }
  112. if clipped.x + clipped.w > self.x + self.w {
  113. clipped.w = self.x + self.w - clipped.x;
  114. }
  115. if clipped.y + clipped.h > self.y + self.h {
  116. clipped.h = self.y + self.h - clipped.y;
  117. }
  118. Some(clipped)
  119. }
  120. pub fn clip_point(&self, point: &mut Point) {
  121. if point.x < self.x {
  122. point.x = self.x;
  123. }
  124. if point.y < self.y {
  125. point.y = self.y;
  126. }
  127. if point.x > self.x + self.w {
  128. point.x = self.x + self.w;
  129. }
  130. if point.y > self.y + self.h {
  131. point.y = self.y + self.h;
  132. }
  133. }
  134. pub fn contains(&self, point: &Point) -> bool {
  135. self.x <= point.x &&
  136. point.x <= self.x + self.w &&
  137. self.y <= point.y &&
  138. point.y <= self.y + self.h
  139. }
  140. pub fn rhs(&self) -> f32 {
  141. self.x + self.w
  142. }
  143. pub fn bhs(&self) -> f32 {
  144. self.y + self.h
  145. }
  146. pub fn top_left(&self) -> Point {
  147. Point { x: self.x, y: self.y }
  148. }
  149. pub fn bottom_right(&self) -> Point {
  150. Point { x: self.x + self.w, y: self.y + self.h }
  151. }
  152. pub fn includes(&self, child: &Self) -> bool {
  153. self.contains(&child.top_left()) && self.contains(&child.bottom_right())
  154. }
  155. }
  156. pub type RenderApiPtr = Arc<RenderApi>;
  157. pub struct RenderApi {
  158. method_req: mpsc::Sender<GraphicsMethod>,
  159. }
  160. impl RenderApi {
  161. pub fn new(method_req: mpsc::Sender<GraphicsMethod>) -> Arc<Self> {
  162. Arc::new(Self { method_req })
  163. }
  164. pub async fn new_texture(&self, width: u16, height: u16, data: Vec<u8>) -> Result<TextureId> {
  165. let (sendr, recvr) = async_channel::bounded(1);
  166. let method = GraphicsMethod::NewTexture((width, height, data, sendr));
  167. self.method_req.send(method).map_err(|_| Error::GfxWindowClosed)?;
  168. let texture_id = recvr.recv().await.map_err(|_| Error::GfxWindowClosed)?;
  169. Ok(texture_id)
  170. }
  171. pub fn delete_texture(&self, texture: TextureId) {
  172. let method = GraphicsMethod::DeleteTexture(texture);
  173. // Ignore any error
  174. let _ = self.method_req.send(method);
  175. }
  176. pub async fn new_vertex_buffer(&self, verts: Vec<Vertex>) -> Result<BufferId> {
  177. let (sendr, recvr) = async_channel::bounded(1);
  178. let method = GraphicsMethod::NewVertexBuffer((verts, sendr));
  179. self.method_req.send(method).map_err(|_| Error::GfxWindowClosed)?;
  180. let buffer = recvr.recv().await.map_err(|_| Error::GfxWindowClosed)?;
  181. Ok(buffer)
  182. }
  183. pub async fn new_index_buffer(&self, indices: Vec<u16>) -> Result<BufferId> {
  184. let (sendr, recvr) = async_channel::bounded(1);
  185. let method = GraphicsMethod::NewIndexBuffer((indices, sendr));
  186. self.method_req.send(method).map_err(|_| Error::GfxWindowClosed)?;
  187. let buffer = recvr.recv().await.map_err(|_| Error::GfxWindowClosed)?;
  188. Ok(buffer)
  189. }
  190. pub fn delete_buffer(&self, buffer: BufferId) {
  191. let method = GraphicsMethod::DeleteBuffer(buffer);
  192. // Ignore any error
  193. let _ = self.method_req.send(method);
  194. }
  195. pub async fn replace_draw_calls(&self, dcs: Vec<(u64, DrawCall)>) {
  196. let method = GraphicsMethod::ReplaceDrawCalls(dcs);
  197. // Ignore any error
  198. let _ = self.method_req.send(method);
  199. }
  200. }
  201. #[derive(Clone, Debug)]
  202. pub struct DrawMesh {
  203. pub vertex_buffer: BufferId,
  204. pub index_buffer: BufferId,
  205. pub texture: Option<TextureId>,
  206. pub num_elements: i32,
  207. }
  208. #[derive(Debug)]
  209. pub enum DrawInstruction {
  210. ApplyViewport(Rectangle),
  211. ApplyMatrix(glam::Mat4),
  212. Draw(DrawMesh),
  213. }
  214. #[derive(Debug)]
  215. pub struct DrawCall {
  216. pub instrs: Vec<DrawInstruction>,
  217. pub dcs: Vec<u64>,
  218. pub z_index: u32,
  219. }
  220. struct RenderContext<'a> {
  221. ctx: &'a mut Box<dyn RenderingBackend>,
  222. draw_calls: &'a HashMap<u64, DrawCall>,
  223. uniforms_data: [u8; 128],
  224. white_texture: TextureId,
  225. }
  226. impl<'a> RenderContext<'a> {
  227. fn draw(&mut self) {
  228. if DEBUG_RENDER {
  229. debug!(target: "gfx", "RenderContext::draw()");
  230. }
  231. self.draw_call(&self.draw_calls[&0], 0);
  232. if DEBUG_RENDER {
  233. debug!(target: "gfx", "RenderContext::draw() [DONE]");
  234. }
  235. }
  236. fn draw_call(&mut self, draw_call: &DrawCall, indent: u32) {
  237. let ws = if DEBUG_RENDER { " ".repeat(indent as usize * 4) } else { String::new() };
  238. for instr in &draw_call.instrs {
  239. match instr {
  240. DrawInstruction::ApplyViewport(view) => {
  241. if DEBUG_RENDER {
  242. debug!(target: "gfx", "{}apply_viewport({:?})", ws, view);
  243. }
  244. let (_, screen_height) = window::screen_size();
  245. let view_x = view.x.round() as i32;
  246. let view_y = screen_height - (view.y + view.h);
  247. let view_y = view_y.round() as i32;
  248. let view_w = view.w.round() as i32;
  249. let view_h = view.h.round() as i32;
  250. self.ctx.apply_viewport(view_x, view_y, view_w, view_h);
  251. self.ctx.apply_scissor_rect(view_x, view_y, view_w, view_h);
  252. }
  253. DrawInstruction::ApplyMatrix(model) => {
  254. if DEBUG_RENDER {
  255. debug!(target: "gfx", "{}apply_matrix(", ws);
  256. debug!(target: "gfx", "{} {:?}", ws, model.row(0).to_array());
  257. debug!(target: "gfx", "{} {:?}", ws, model.row(1).to_array());
  258. debug!(target: "gfx", "{} {:?}", ws, model.row(2).to_array());
  259. debug!(target: "gfx", "{} {:?}", ws, model.row(3).to_array());
  260. debug!(target: "gfx", "{})", ws);
  261. }
  262. let data: [u8; 64] = unsafe { std::mem::transmute_copy(model) };
  263. self.uniforms_data[64..].copy_from_slice(&data);
  264. self.ctx.apply_uniforms_from_bytes(
  265. self.uniforms_data.as_ptr(),
  266. self.uniforms_data.len(),
  267. );
  268. }
  269. DrawInstruction::Draw(mesh) => {
  270. if DEBUG_RENDER {
  271. debug!(target: "gfx", "{}draw({:?})", ws, mesh);
  272. }
  273. let texture = match mesh.texture {
  274. Some(texture) => texture,
  275. None => self.white_texture,
  276. };
  277. let bindings = Bindings {
  278. vertex_buffers: vec![mesh.vertex_buffer],
  279. index_buffer: mesh.index_buffer,
  280. images: vec![texture],
  281. };
  282. self.ctx.apply_bindings(&bindings);
  283. self.ctx.draw(0, mesh.num_elements, 1);
  284. }
  285. }
  286. }
  287. let mut draw_calls: Vec<_> =
  288. draw_call.dcs.iter().map(|key| &self.draw_calls[key]).collect();
  289. draw_calls.sort_unstable_by_key(|dc| dc.z_index);
  290. for dc in draw_calls {
  291. self.draw_call(dc, indent + 1);
  292. }
  293. }
  294. }
  295. #[derive(Debug)]
  296. pub enum GraphicsMethod {
  297. NewTexture((u16, u16, Vec<u8>, async_channel::Sender<TextureId>)),
  298. DeleteTexture(TextureId),
  299. NewVertexBuffer((Vec<Vertex>, async_channel::Sender<BufferId>)),
  300. NewIndexBuffer((Vec<u16>, async_channel::Sender<BufferId>)),
  301. DeleteBuffer(BufferId),
  302. ReplaceDrawCalls(Vec<(u64, DrawCall)>),
  303. }
  304. pub type GraphicsEventPublisherPtr = Arc<GraphicsEventPublisher>;
  305. pub struct GraphicsEventPublisher {
  306. lock_resize: SyncMutex<Option<SubscriptionId>>,
  307. resize: PublisherPtr<(f32, f32)>,
  308. lock_mouse_move: SyncMutex<Option<SubscriptionId>>,
  309. mouse_move: PublisherPtr<(f32, f32)>,
  310. lock_mouse_wheel: SyncMutex<Option<SubscriptionId>>,
  311. mouse_wheel: PublisherPtr<(f32, f32)>,
  312. lock_mouse_btn_down: SyncMutex<Option<SubscriptionId>>,
  313. mouse_btn_down: PublisherPtr<(MouseButton, f32, f32)>,
  314. lock_mouse_btn_up: SyncMutex<Option<SubscriptionId>>,
  315. mouse_btn_up: PublisherPtr<(MouseButton, f32, f32)>,
  316. lock_char: SyncMutex<Option<SubscriptionId>>,
  317. chr: PublisherPtr<(char, KeyMods, bool)>,
  318. lock_key_down: SyncMutex<Option<SubscriptionId>>,
  319. key_down: PublisherPtr<(KeyCode, KeyMods, bool)>,
  320. lock_key_up: SyncMutex<Option<SubscriptionId>>,
  321. key_up: PublisherPtr<(KeyCode, KeyMods)>,
  322. lock_touch: SyncMutex<Option<SubscriptionId>>,
  323. touch: PublisherPtr<(TouchPhase, u64, f32, f32)>,
  324. }
  325. impl GraphicsEventPublisher {
  326. pub fn new() -> Arc<Self> {
  327. Arc::new(Self {
  328. lock_resize: SyncMutex::new(None),
  329. resize: Publisher::new(),
  330. lock_mouse_move: SyncMutex::new(None),
  331. mouse_move: Publisher::new(),
  332. lock_mouse_wheel: SyncMutex::new(None),
  333. mouse_wheel: Publisher::new(),
  334. lock_mouse_btn_down: SyncMutex::new(None),
  335. mouse_btn_down: Publisher::new(),
  336. lock_mouse_btn_up: SyncMutex::new(None),
  337. mouse_btn_up: Publisher::new(),
  338. lock_char: SyncMutex::new(None),
  339. chr: Publisher::new(),
  340. lock_key_down: SyncMutex::new(None),
  341. key_down: Publisher::new(),
  342. lock_key_up: SyncMutex::new(None),
  343. key_up: Publisher::new(),
  344. lock_touch: SyncMutex::new(None),
  345. touch: Publisher::new(),
  346. })
  347. }
  348. fn lock_resize(&self, sub_id: SubscriptionId) {
  349. *self.lock_resize.lock().unwrap() = Some(sub_id);
  350. }
  351. fn unlock_resize(&self) {
  352. *self.lock_resize.lock().unwrap() = None;
  353. }
  354. fn lock_mouse_move(&self, sub_id: SubscriptionId) {
  355. *self.lock_mouse_move.lock().unwrap() = Some(sub_id);
  356. }
  357. fn unlock_mouse_move(&self) {
  358. *self.lock_mouse_move.lock().unwrap() = None;
  359. }
  360. fn lock_mouse_wheel(&self, sub_id: SubscriptionId) {
  361. *self.lock_mouse_wheel.lock().unwrap() = Some(sub_id);
  362. }
  363. fn unlock_mouse_wheel(&self) {
  364. *self.lock_mouse_wheel.lock().unwrap() = None;
  365. }
  366. fn lock_mouse_btn_down(&self, sub_id: SubscriptionId) {
  367. *self.lock_mouse_btn_down.lock().unwrap() = Some(sub_id);
  368. }
  369. fn unlock_mouse_btn_down(&self) {
  370. *self.lock_mouse_btn_down.lock().unwrap() = None;
  371. }
  372. fn lock_mouse_btn_up(&self, sub_id: SubscriptionId) {
  373. *self.lock_mouse_btn_up.lock().unwrap() = Some(sub_id);
  374. }
  375. fn unlock_mouse_btn_up(&self) {
  376. *self.lock_mouse_btn_up.lock().unwrap() = None;
  377. }
  378. fn lock_char(&self, sub_id: SubscriptionId) {
  379. *self.lock_char.lock().unwrap() = Some(sub_id);
  380. }
  381. fn unlock_char(&self) {
  382. *self.lock_char.lock().unwrap() = None;
  383. }
  384. fn lock_key_down(&self, sub_id: SubscriptionId) {
  385. *self.lock_key_down.lock().unwrap() = Some(sub_id);
  386. }
  387. fn unlock_key_down(&self) {
  388. *self.lock_key_down.lock().unwrap() = None;
  389. }
  390. fn lock_key_up(&self, sub_id: SubscriptionId) {
  391. *self.lock_key_up.lock().unwrap() = Some(sub_id);
  392. }
  393. fn unlock_key_up(&self) {
  394. *self.lock_key_up.lock().unwrap() = None;
  395. }
  396. fn lock_touch(&self, sub_id: SubscriptionId) {
  397. *self.lock_touch.lock().unwrap() = Some(sub_id);
  398. }
  399. fn unlock_touch(&self) {
  400. *self.lock_touch.lock().unwrap() = None;
  401. }
  402. fn notify_resize(&self, w: f32, h: f32) {
  403. let ev = (w, h);
  404. let locked = self.lock_resize.lock().unwrap().clone();
  405. if let Some(locked) = locked {
  406. self.resize.notify_with_include(ev, &[locked]);
  407. } else {
  408. self.resize.notify(ev);
  409. }
  410. }
  411. fn notify_mouse_move(&self, x: f32, y: f32) {
  412. let ev = (x, y);
  413. let locked = self.lock_mouse_move.lock().unwrap().clone();
  414. if let Some(locked) = locked {
  415. self.mouse_move.notify_with_include(ev, &[locked]);
  416. } else {
  417. self.mouse_move.notify(ev);
  418. }
  419. }
  420. fn notify_mouse_wheel(&self, x: f32, y: f32) {
  421. let ev = (x, y);
  422. let locked = self.lock_mouse_wheel.lock().unwrap().clone();
  423. if let Some(locked) = locked {
  424. self.mouse_wheel.notify_with_include(ev, &[locked]);
  425. } else {
  426. self.mouse_wheel.notify(ev);
  427. }
  428. }
  429. fn notify_mouse_btn_down(&self, button: MouseButton, x: f32, y: f32) {
  430. let ev = (button, x, y);
  431. let locked = self.lock_mouse_btn_down.lock().unwrap().clone();
  432. if let Some(locked) = locked {
  433. self.mouse_btn_down.notify_with_include(ev, &[locked]);
  434. } else {
  435. self.mouse_btn_down.notify(ev);
  436. }
  437. }
  438. fn notify_mouse_btn_up(&self, button: MouseButton, x: f32, y: f32) {
  439. let ev = (button, x, y);
  440. let locked = self.lock_mouse_btn_up.lock().unwrap().clone();
  441. if let Some(locked) = locked {
  442. self.mouse_btn_up.notify_with_include(ev, &[locked]);
  443. } else {
  444. self.mouse_btn_up.notify(ev);
  445. }
  446. }
  447. fn notify_char(&self, chr: char, mods: KeyMods, repeat: bool) {
  448. let ev = (chr, mods, repeat);
  449. let locked = self.lock_char.lock().unwrap().clone();
  450. if let Some(locked) = locked {
  451. self.chr.notify_with_include(ev, &[locked]);
  452. } else {
  453. self.chr.notify(ev);
  454. }
  455. }
  456. fn notify_key_down(&self, key: KeyCode, mods: KeyMods, repeat: bool) {
  457. let ev = (key, mods, repeat);
  458. let locked = self.lock_key_down.lock().unwrap().clone();
  459. if let Some(locked) = locked {
  460. self.key_down.notify_with_include(ev, &[locked]);
  461. } else {
  462. self.key_down.notify(ev);
  463. }
  464. }
  465. fn notify_key_up(&self, key: KeyCode, mods: KeyMods) {
  466. let ev = (key, mods);
  467. let locked = self.lock_key_up.lock().unwrap().clone();
  468. if let Some(locked) = locked {
  469. self.key_up.notify_with_include(ev, &[locked]);
  470. } else {
  471. self.key_up.notify(ev);
  472. }
  473. }
  474. fn notify_touch(&self, phase: TouchPhase, id: u64, x: f32, y: f32) {
  475. let ev = (phase, id, x, y);
  476. let locked = self.lock_touch.lock().unwrap().clone();
  477. if let Some(locked) = locked {
  478. self.touch.notify_with_include(ev, &[locked]);
  479. } else {
  480. self.touch.notify(ev);
  481. }
  482. }
  483. pub fn subscribe_resize(&self) -> Subscription<(f32, f32)> {
  484. self.resize.clone().subscribe()
  485. }
  486. pub fn subscribe_mouse_move(&self) -> Subscription<(f32, f32)> {
  487. self.mouse_move.clone().subscribe()
  488. }
  489. pub fn subscribe_mouse_wheel(&self) -> Subscription<(f32, f32)> {
  490. self.mouse_wheel.clone().subscribe()
  491. }
  492. pub fn subscribe_mouse_btn_down(&self) -> Subscription<(MouseButton, f32, f32)> {
  493. self.mouse_btn_down.clone().subscribe()
  494. }
  495. pub fn subscribe_mouse_btn_up(&self) -> Subscription<(MouseButton, f32, f32)> {
  496. self.mouse_btn_up.clone().subscribe()
  497. }
  498. pub fn subscribe_char(&self) -> Subscription<(char, KeyMods, bool)> {
  499. self.chr.clone().subscribe()
  500. }
  501. pub fn subscribe_key_down(&self) -> Subscription<(KeyCode, KeyMods, bool)> {
  502. self.key_down.clone().subscribe()
  503. }
  504. pub fn subscribe_key_up(&self) -> Subscription<(KeyCode, KeyMods)> {
  505. self.key_up.clone().subscribe()
  506. }
  507. pub fn subscribe_touch(&self) -> Subscription<(TouchPhase, u64, f32, f32)> {
  508. self.touch.clone().subscribe()
  509. }
  510. }
  511. struct Stage {
  512. async_runtime: AsyncRuntime,
  513. ctx: Box<dyn RenderingBackend>,
  514. pipeline: Pipeline,
  515. white_texture: TextureId,
  516. draw_calls: HashMap<u64, DrawCall>,
  517. last_draw_time: Option<Instant>,
  518. method_rep: mpsc::Receiver<GraphicsMethod>,
  519. event_pub: GraphicsEventPublisherPtr,
  520. }
  521. impl Stage {
  522. pub fn new(
  523. async_runtime: AsyncRuntime,
  524. method_rep: mpsc::Receiver<GraphicsMethod>,
  525. event_pub: GraphicsEventPublisherPtr,
  526. ) -> Self {
  527. let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();
  528. // Maybe should be patched upstream since inconsistent behaviour
  529. // Needs testing on other platforms too.
  530. #[cfg(target_os = "android")]
  531. {
  532. let (screen_width, screen_height) = window::screen_size();
  533. event_pub.notify_resize(screen_width, screen_height);
  534. }
  535. let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
  536. let mut shader_meta: ShaderMeta = shader::meta();
  537. shader_meta.uniforms.uniforms.push(UniformDesc::new("Projection", UniformType::Mat4));
  538. shader_meta.uniforms.uniforms.push(UniformDesc::new("Model", UniformType::Mat4));
  539. let shader = ctx
  540. .new_shader(
  541. match ctx.info().backend {
  542. Backend::OpenGl => ShaderSource::Glsl {
  543. vertex: shader::GL_VERTEX,
  544. fragment: shader::GL_FRAGMENT,
  545. },
  546. Backend::Metal => ShaderSource::Msl { program: shader::METAL },
  547. },
  548. shader_meta,
  549. )
  550. .unwrap();
  551. let params = PipelineParams {
  552. color_blend: Some(BlendState::new(
  553. Equation::Add,
  554. BlendFactor::Value(BlendValue::SourceAlpha),
  555. BlendFactor::OneMinusValue(BlendValue::SourceAlpha),
  556. )),
  557. ..Default::default()
  558. };
  559. let pipeline = ctx.new_pipeline(
  560. &[BufferLayout::default()],
  561. &[
  562. VertexAttribute::new("in_pos", VertexFormat::Float2),
  563. VertexAttribute::new("in_color", VertexFormat::Float4),
  564. VertexAttribute::new("in_uv", VertexFormat::Float2),
  565. ],
  566. shader,
  567. params,
  568. );
  569. Stage {
  570. async_runtime,
  571. ctx,
  572. pipeline,
  573. white_texture,
  574. draw_calls: HashMap::from([(0, DrawCall { instrs: vec![], dcs: vec![], z_index: 0 })]),
  575. last_draw_time: None,
  576. method_rep,
  577. event_pub,
  578. }
  579. }
  580. fn method_new_texture(
  581. &mut self,
  582. width: u16,
  583. height: u16,
  584. data: Vec<u8>,
  585. sendr: async_channel::Sender<TextureId>,
  586. ) {
  587. let texture = self.ctx.new_texture_from_rgba8(width, height, &data);
  588. //debug!(target: "gfx2", "Invoked method: new_texture({}, {}, ...) -> {:?}",
  589. // width, height, texture);
  590. //debug!(target: "gfx2", "Invoked method: new_texture({}, {}, ...) -> {:?}\n{}",
  591. // width, height, texture,
  592. // ansi_texture(width as usize, height as usize, &data));
  593. sendr.try_send(texture).unwrap();
  594. }
  595. fn method_delete_texture(&mut self, texture: TextureId) {
  596. //debug!(target: "gfx2", "Invoked method: delete_texture({:?})", texture);
  597. self.ctx.delete_texture(texture);
  598. }
  599. fn method_new_vertex_buffer(
  600. &mut self,
  601. verts: Vec<Vertex>,
  602. sendr: async_channel::Sender<BufferId>,
  603. ) {
  604. let buffer = self.ctx.new_buffer(
  605. BufferType::VertexBuffer,
  606. BufferUsage::Immutable,
  607. BufferSource::slice(&verts),
  608. );
  609. //debug!(target: "gfx2", "Invoked method: new_vertex_buffer({:?}) -> {:?}", verts, buffer);
  610. sendr.try_send(buffer).unwrap();
  611. }
  612. fn method_new_index_buffer(
  613. &mut self,
  614. indices: Vec<u16>,
  615. sendr: async_channel::Sender<BufferId>,
  616. ) {
  617. let buffer = self.ctx.new_buffer(
  618. BufferType::IndexBuffer,
  619. BufferUsage::Immutable,
  620. BufferSource::slice(&indices),
  621. );
  622. //debug!(target: "gfx2", "Invoked method: new_index_buffer({:?}) -> {:?}", indices, buffer);
  623. sendr.try_send(buffer).unwrap();
  624. }
  625. fn method_delete_buffer(&mut self, buffer: BufferId) {
  626. //debug!(target: "gfx2", "Invoked method: delete_buffer({:?})", buffer);
  627. self.ctx.delete_buffer(buffer);
  628. }
  629. fn method_replace_draw_calls(&mut self, dcs: Vec<(u64, DrawCall)>) {
  630. //debug!(target: "gfx2", "Invoked method: replace_draw_calls({:?})", dcs);
  631. for (key, val) in dcs {
  632. self.draw_calls.insert(key, val);
  633. }
  634. }
  635. }
  636. impl EventHandler for Stage {
  637. fn update(&mut self) {
  638. if self.last_draw_time.is_none() {
  639. return
  640. }
  641. // Only allow 20 ms, process as much as we can during that time
  642. let elapsed_since_draw = self.last_draw_time.unwrap().elapsed();
  643. // We're long overdue a redraw. Exit for now
  644. if elapsed_since_draw > Duration::from_millis(20) {
  645. return
  646. }
  647. // The next redraw must happen 20ms since its last one.
  648. // Calculate how much time is remaining until then.
  649. let allowed_time = Duration::from_millis(20) - elapsed_since_draw;
  650. let deadline = Instant::now() + allowed_time;
  651. loop {
  652. let Ok(method) = self.method_rep.recv_deadline(deadline) else { break };
  653. //debug!(target: "gfx", "Received method: {:?}", method);
  654. match method {
  655. GraphicsMethod::NewTexture((width, height, data, sendr)) => {
  656. self.method_new_texture(width, height, data, sendr)
  657. }
  658. GraphicsMethod::DeleteTexture(texture) => self.method_delete_texture(texture),
  659. GraphicsMethod::NewVertexBuffer((verts, sendr)) => {
  660. self.method_new_vertex_buffer(verts, sendr)
  661. }
  662. GraphicsMethod::NewIndexBuffer((indices, sendr)) => {
  663. self.method_new_index_buffer(indices, sendr)
  664. }
  665. GraphicsMethod::DeleteBuffer(buffer) => self.method_delete_buffer(buffer),
  666. GraphicsMethod::ReplaceDrawCalls(dcs) => self.method_replace_draw_calls(dcs),
  667. };
  668. }
  669. }
  670. fn draw(&mut self) {
  671. self.last_draw_time = Some(Instant::now());
  672. self.ctx.begin_default_pass(PassAction::Nothing);
  673. self.ctx.apply_pipeline(&self.pipeline);
  674. // This will make the top left (0, 0) and the bottom right (1, 1)
  675. // Default is (-1, 1) -> (1, -1)
  676. let proj = glam::Mat4::from_translation(glam::Vec3::new(-1., 1., 0.)) *
  677. glam::Mat4::from_scale(glam::Vec3::new(2., -2., 1.));
  678. let mut uniforms_data = [0u8; 128];
  679. let data: [u8; 64] = unsafe { std::mem::transmute_copy(&proj) };
  680. uniforms_data[0..64].copy_from_slice(&data);
  681. //let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
  682. //uniforms_data[64..].copy_from_slice(&data);
  683. assert_eq!(128, 2 * UniformType::Mat4.size());
  684. let mut render_ctx = RenderContext {
  685. ctx: &mut self.ctx,
  686. draw_calls: &self.draw_calls,
  687. uniforms_data,
  688. white_texture: self.white_texture,
  689. };
  690. render_ctx.draw();
  691. self.ctx.commit_frame();
  692. }
  693. fn resize_event(&mut self, width: f32, height: f32) {
  694. self.event_pub.notify_resize(width, height);
  695. }
  696. fn mouse_motion_event(&mut self, x: f32, y: f32) {
  697. self.event_pub.notify_mouse_move(x, y);
  698. }
  699. fn mouse_wheel_event(&mut self, x: f32, y: f32) {
  700. self.event_pub.notify_mouse_wheel(x, y);
  701. }
  702. fn mouse_button_down_event(&mut self, button: MouseButton, x: f32, y: f32) {
  703. self.event_pub.notify_mouse_btn_down(button, x, y);
  704. }
  705. fn mouse_button_up_event(&mut self, button: MouseButton, x: f32, y: f32) {
  706. self.event_pub.notify_mouse_btn_up(button, x, y);
  707. }
  708. fn char_event(&mut self, chr: char, mods: KeyMods, repeat: bool) {
  709. self.event_pub.notify_char(chr, mods, repeat);
  710. }
  711. fn key_down_event(&mut self, keycode: KeyCode, mods: KeyMods, repeat: bool) {
  712. self.event_pub.notify_key_down(keycode, mods, repeat);
  713. }
  714. fn key_up_event(&mut self, keycode: KeyCode, mods: KeyMods) {
  715. self.event_pub.notify_key_up(keycode, mods);
  716. }
  717. /// The id corresponds to multi-touch. Multiple touch events have different ids.
  718. fn touch_event(&mut self, phase: TouchPhase, id: u64, x: f32, y: f32) {
  719. self.event_pub.notify_touch(phase, id, x, y);
  720. }
  721. fn quit_requested_event(&mut self) {
  722. self.async_runtime.stop();
  723. }
  724. }
  725. pub fn run_gui(
  726. async_runtime: AsyncRuntime,
  727. method_rep: mpsc::Receiver<GraphicsMethod>,
  728. event_pub: GraphicsEventPublisherPtr,
  729. ) {
  730. let mut conf = miniquad::conf::Conf {
  731. high_dpi: true,
  732. window_resizable: true,
  733. platform: miniquad::conf::Platform {
  734. linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
  735. wayland_use_fallback_decorations: false,
  736. ..Default::default()
  737. },
  738. ..Default::default()
  739. };
  740. let metal = std::env::args().nth(1).as_deref() == Some("metal");
  741. conf.platform.apple_gfx_api =
  742. if metal { conf::AppleGfxApi::Metal } else { conf::AppleGfxApi::OpenGl };
  743. miniquad::start(conf, || Box::new(Stage::new(async_runtime, method_rep, event_pub)));
  744. }