mod.rs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  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::system::CondVar;
  19. use darkfi_serial::{async_trait, SerialDecodable, SerialEncodable};
  20. use futures::AsyncWriteExt;
  21. use log::debug;
  22. use miniquad::{
  23. conf, window, Backend, Bindings, BlendFactor, BlendState, BlendValue, BufferLayout,
  24. BufferSource, BufferType, BufferUsage, Equation, EventHandler, KeyCode, KeyMods, MouseButton,
  25. PassAction, Pipeline, PipelineParams, RenderingBackend, ShaderMeta, ShaderSource, TouchPhase,
  26. UniformDesc, UniformType, VertexAttribute, VertexFormat,
  27. };
  28. use std::{
  29. collections::HashMap,
  30. sync::{mpsc, Arc, Mutex as SyncMutex},
  31. time::{Duration, Instant},
  32. };
  33. mod linalg;
  34. pub use linalg::{Dimension, Point, Rectangle};
  35. mod shader;
  36. use crate::{
  37. app::{AppPtr, AsyncRuntime},
  38. error::{Error, Result},
  39. pubsub::{Publisher, PublisherPtr, Subscription, SubscriptionId},
  40. util::ansi_texture,
  41. };
  42. pub type GfxTextureId = u32;
  43. pub type GfxBufferId = u32;
  44. // This is very noisy so suppress output by default
  45. const DEBUG_RENDER: bool = false;
  46. const DEBUG_GFXAPI: bool = false;
  47. const DEBUG_DRAW_LOG: bool = false;
  48. #[derive(Clone, Debug, SerialEncodable, SerialDecodable)]
  49. #[repr(C)]
  50. pub struct Vertex {
  51. pub pos: [f32; 2],
  52. pub color: [f32; 4],
  53. pub uv: [f32; 2],
  54. }
  55. impl Vertex {
  56. pub fn pos(&self) -> Point {
  57. self.pos.into()
  58. }
  59. pub fn set_pos(&mut self, pos: &Point) {
  60. self.pos = pos.as_arr();
  61. }
  62. }
  63. pub type ManagedTexturePtr = Arc<ManagedTexture>;
  64. /// Auto-deletes texture on drop
  65. #[derive(Clone)]
  66. pub struct ManagedTexture {
  67. id: GfxTextureId,
  68. render_api: RenderApi,
  69. }
  70. impl Drop for ManagedTexture {
  71. fn drop(&mut self) {
  72. self.render_api.delete_unmanaged_texture(self.id);
  73. }
  74. }
  75. impl std::fmt::Debug for ManagedTexture {
  76. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  77. f.debug_struct("ManagedTexture").field("id", &self.id).finish()
  78. }
  79. }
  80. pub type ManagedBufferPtr = Arc<ManagedBuffer>;
  81. /// Auto-deletes buffer on drop
  82. #[derive(Clone)]
  83. pub struct ManagedBuffer {
  84. id: GfxBufferId,
  85. render_api: RenderApi,
  86. }
  87. impl Drop for ManagedBuffer {
  88. fn drop(&mut self) {
  89. self.render_api.delete_unmanaged_buffer(self.id);
  90. }
  91. }
  92. impl std::fmt::Debug for ManagedBuffer {
  93. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  94. f.debug_struct("ManagedBuffer").field("id", &self.id).finish()
  95. }
  96. }
  97. #[derive(Clone)]
  98. pub struct RenderApi {
  99. method_req: mpsc::Sender<GraphicsMethod>,
  100. }
  101. impl RenderApi {
  102. pub fn new(method_req: mpsc::Sender<GraphicsMethod>) -> Self {
  103. Self { method_req }
  104. }
  105. fn new_unmanaged_texture(&self, width: u16, height: u16, data: Vec<u8>) -> GfxTextureId {
  106. let gfx_texture_id = rand::random();
  107. let method = GraphicsMethod::NewTexture((width, height, data, gfx_texture_id));
  108. let _ = self.method_req.send(method);
  109. gfx_texture_id
  110. }
  111. pub fn new_texture(&self, width: u16, height: u16, data: Vec<u8>) -> ManagedTexturePtr {
  112. Arc::new(ManagedTexture {
  113. id: self.new_unmanaged_texture(width, height, data),
  114. render_api: self.clone(),
  115. })
  116. }
  117. fn delete_unmanaged_texture(&self, texture: GfxTextureId) {
  118. let method = GraphicsMethod::DeleteTexture(texture);
  119. let _ = self.method_req.send(method);
  120. }
  121. fn new_unmanaged_vertex_buffer(&self, verts: Vec<Vertex>) -> GfxBufferId {
  122. let gfx_buffer_id = rand::random();
  123. let method = GraphicsMethod::NewVertexBuffer((verts, gfx_buffer_id));
  124. let _ = self.method_req.send(method);
  125. gfx_buffer_id
  126. }
  127. fn new_unmanaged_index_buffer(&self, indices: Vec<u16>) -> GfxBufferId {
  128. let gfx_buffer_id = rand::random();
  129. let method = GraphicsMethod::NewIndexBuffer((indices, gfx_buffer_id));
  130. let _ = self.method_req.send(method);
  131. gfx_buffer_id
  132. }
  133. pub fn new_vertex_buffer(&self, verts: Vec<Vertex>) -> ManagedBufferPtr {
  134. Arc::new(ManagedBuffer {
  135. id: self.new_unmanaged_vertex_buffer(verts),
  136. render_api: self.clone(),
  137. })
  138. }
  139. pub fn new_index_buffer(&self, indices: Vec<u16>) -> ManagedBufferPtr {
  140. Arc::new(ManagedBuffer {
  141. id: self.new_unmanaged_index_buffer(indices),
  142. render_api: self.clone(),
  143. })
  144. }
  145. fn delete_unmanaged_buffer(&self, buffer: GfxBufferId) {
  146. let method = GraphicsMethod::DeleteBuffer(buffer);
  147. let _ = self.method_req.send(method);
  148. }
  149. pub fn replace_draw_calls(&self, dcs: Vec<(u64, GfxDrawCall)>) {
  150. let method = GraphicsMethod::ReplaceDrawCalls(dcs);
  151. let _ = self.method_req.send(method);
  152. }
  153. }
  154. #[derive(Clone, Debug)]
  155. pub struct GfxDrawMesh {
  156. pub vertex_buffer: ManagedBufferPtr,
  157. pub index_buffer: ManagedBufferPtr,
  158. pub texture: Option<ManagedTexturePtr>,
  159. pub num_elements: i32,
  160. }
  161. impl GfxDrawMesh {
  162. fn compile(
  163. self,
  164. textures: &HashMap<GfxTextureId, miniquad::TextureId>,
  165. buffers: &HashMap<GfxBufferId, miniquad::BufferId>,
  166. ) -> DrawMesh {
  167. let buffers_keep_alive = [self.vertex_buffer.clone(), self.index_buffer.clone()];
  168. DrawMesh {
  169. vertex_buffer: buffers[&self.vertex_buffer.id],
  170. index_buffer: buffers[&self.index_buffer.id],
  171. buffers_keep_alive,
  172. texture: self.texture.map(|t| (t.clone(), textures[&t.id])),
  173. num_elements: self.num_elements,
  174. }
  175. }
  176. }
  177. #[derive(Debug, Clone)]
  178. pub enum GfxDrawInstruction {
  179. SetScale(f32),
  180. Move(Point),
  181. ApplyView(Rectangle),
  182. Draw(GfxDrawMesh),
  183. }
  184. impl GfxDrawInstruction {
  185. fn compile(
  186. self,
  187. textures: &HashMap<GfxTextureId, miniquad::TextureId>,
  188. buffers: &HashMap<GfxBufferId, miniquad::BufferId>,
  189. ) -> DrawInstruction {
  190. match self {
  191. Self::SetScale(scale) => DrawInstruction::SetScale(scale),
  192. Self::Move(off) => DrawInstruction::Move(off),
  193. Self::ApplyView(view) => DrawInstruction::ApplyView(view),
  194. Self::Draw(mesh) => DrawInstruction::Draw(mesh.compile(textures, buffers)),
  195. }
  196. }
  197. }
  198. #[derive(Clone, Debug, Default)]
  199. pub struct GfxDrawCall {
  200. pub instrs: Vec<GfxDrawInstruction>,
  201. pub dcs: Vec<u64>,
  202. pub z_index: u32,
  203. }
  204. impl GfxDrawCall {
  205. fn compile(
  206. self,
  207. textures: &HashMap<GfxTextureId, miniquad::TextureId>,
  208. buffers: &HashMap<GfxBufferId, miniquad::BufferId>,
  209. ) -> DrawCall {
  210. DrawCall {
  211. instrs: self.instrs.into_iter().map(|i| i.compile(textures, buffers)).collect(),
  212. dcs: self.dcs,
  213. z_index: self.z_index,
  214. }
  215. }
  216. }
  217. #[derive(Clone, Debug)]
  218. struct DrawMesh {
  219. vertex_buffer: miniquad::BufferId,
  220. index_buffer: miniquad::BufferId,
  221. /// Keeps the buffers alive for the duration of this draw call
  222. buffers_keep_alive: [ManagedBufferPtr; 2],
  223. texture: Option<(ManagedTexturePtr, miniquad::TextureId)>,
  224. num_elements: i32,
  225. }
  226. #[derive(Debug, Clone)]
  227. enum DrawInstruction {
  228. SetScale(f32),
  229. Move(Point),
  230. ApplyView(Rectangle),
  231. Draw(DrawMesh),
  232. }
  233. #[derive(Debug)]
  234. struct DrawCall {
  235. instrs: Vec<DrawInstruction>,
  236. dcs: Vec<u64>,
  237. z_index: u32,
  238. }
  239. struct RenderContext<'a> {
  240. ctx: &'a mut Box<dyn RenderingBackend>,
  241. draw_calls: &'a HashMap<u64, DrawCall>,
  242. uniforms_data: [u8; 128],
  243. white_texture: miniquad::TextureId,
  244. scale: f32,
  245. view: Rectangle,
  246. cursor: Point,
  247. }
  248. impl<'a> RenderContext<'a> {
  249. fn draw(&mut self) {
  250. if DEBUG_RENDER {
  251. debug!(target: "gfx", "RenderContext::draw()");
  252. }
  253. let curr_pos = Point::zero();
  254. self.draw_call(&self.draw_calls[&0], 0);
  255. if DEBUG_RENDER {
  256. debug!(target: "gfx", "RenderContext::draw() [DONE]");
  257. }
  258. }
  259. fn apply_view(&mut self) {
  260. let view = self.view * self.scale;
  261. let (_, screen_height) = window::screen_size();
  262. let view_x = view.x.round() as i32;
  263. let view_y = screen_height - (view.y + view.h);
  264. let view_y = view_y.round() as i32;
  265. let view_w = view.w.round() as i32;
  266. let view_h = view.h.round() as i32;
  267. // OpenGL does not like negative values here
  268. if view_w <= 0 || view_h <= 0 {
  269. return
  270. }
  271. //if DEBUG_RENDER {
  272. // debug!(target: "gfx", "=> viewport {view_x} {view_y} {view_w} {view_h}");
  273. //}
  274. self.ctx.apply_viewport(view_x, view_y, view_w, view_h);
  275. self.ctx.apply_scissor_rect(view_x, view_y, view_w, view_h);
  276. }
  277. fn apply_model(&mut self) {
  278. let off_x = self.cursor.x / self.view.w;
  279. let off_y = self.cursor.y / self.view.h;
  280. let scale_w = 1. / self.view.w;
  281. let scale_h = 1. / self.view.h;
  282. let model = glam::Mat4::from_translation(glam::Vec3::new(off_x, off_y, 0.)) *
  283. glam::Mat4::from_scale(glam::Vec3::new(scale_w, scale_h, 1.));
  284. let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
  285. self.uniforms_data[64..].copy_from_slice(&data);
  286. self.ctx.apply_uniforms_from_bytes(self.uniforms_data.as_ptr(), self.uniforms_data.len());
  287. }
  288. fn draw_call(&mut self, draw_call: &DrawCall, indent: u32) {
  289. let ws = if DEBUG_RENDER { " ".repeat(indent as usize * 4) } else { String::new() };
  290. let old_view = self.view;
  291. let old_cursor = self.cursor;
  292. for instr in &draw_call.instrs {
  293. match instr {
  294. DrawInstruction::SetScale(scale) => {
  295. self.scale = *scale;
  296. if DEBUG_RENDER {
  297. debug!(target: "gfx", "{ws}set_scale({scale})");
  298. }
  299. }
  300. DrawInstruction::Move(off) => {
  301. self.cursor = old_cursor + *off;
  302. if DEBUG_RENDER {
  303. debug!(target: "gfx",
  304. "{ws}move({off:?}) cursor={:?}, scale={}, view={:?}",
  305. self.cursor, self.scale, self.view
  306. );
  307. }
  308. self.apply_model();
  309. }
  310. DrawInstruction::ApplyView(view) => {
  311. self.view = *view;
  312. if DEBUG_RENDER {
  313. debug!(target: "gfx",
  314. "{ws}apply_view({view:?}) scale={}, view={:?}",
  315. self.scale, self.view
  316. );
  317. }
  318. self.apply_view();
  319. }
  320. DrawInstruction::Draw(mesh) => {
  321. if DEBUG_RENDER {
  322. debug!(target: "gfx", "{ws}draw({mesh:?})");
  323. }
  324. let texture = match mesh.texture {
  325. Some((_, texture)) => texture,
  326. None => self.white_texture,
  327. };
  328. let bindings = Bindings {
  329. vertex_buffers: vec![mesh.vertex_buffer],
  330. index_buffer: mesh.index_buffer,
  331. images: vec![texture],
  332. };
  333. self.ctx.apply_bindings(&bindings);
  334. self.ctx.draw(0, mesh.num_elements, 1);
  335. }
  336. }
  337. }
  338. let mut draw_calls: Vec<_> =
  339. draw_call.dcs.iter().map(|key| (key, &self.draw_calls[key])).collect();
  340. draw_calls.sort_unstable_by_key(|(_, dc)| dc.z_index);
  341. for (dc_key, dc) in draw_calls {
  342. if DEBUG_RENDER {
  343. debug!(target: "gfx", "{ws}drawcall {dc_key}");
  344. }
  345. self.draw_call(dc, indent + 1);
  346. }
  347. self.cursor = old_cursor;
  348. self.apply_model();
  349. self.view = old_view;
  350. self.apply_view();
  351. }
  352. }
  353. #[derive(Clone, Debug)]
  354. pub enum GraphicsMethod {
  355. NewTexture((u16, u16, Vec<u8>, GfxTextureId)),
  356. DeleteTexture(GfxTextureId),
  357. NewVertexBuffer((Vec<Vertex>, GfxBufferId)),
  358. NewIndexBuffer((Vec<u16>, GfxBufferId)),
  359. DeleteBuffer(GfxBufferId),
  360. ReplaceDrawCalls(Vec<(u64, GfxDrawCall)>),
  361. }
  362. pub type GraphicsEventPublisherPtr = Arc<GraphicsEventPublisher>;
  363. pub struct GraphicsEventPublisher {
  364. resize: PublisherPtr<Dimension>,
  365. key_down: PublisherPtr<(KeyCode, KeyMods, bool)>,
  366. key_up: PublisherPtr<(KeyCode, KeyMods)>,
  367. chr: PublisherPtr<(char, KeyMods, bool)>,
  368. mouse_btn_down: PublisherPtr<(MouseButton, Point)>,
  369. mouse_btn_up: PublisherPtr<(MouseButton, Point)>,
  370. mouse_move: PublisherPtr<Point>,
  371. mouse_wheel: PublisherPtr<Point>,
  372. touch: PublisherPtr<(TouchPhase, u64, Point)>,
  373. }
  374. impl GraphicsEventPublisher {
  375. pub fn new() -> Arc<Self> {
  376. Arc::new(Self {
  377. resize: Publisher::new(),
  378. key_down: Publisher::new(),
  379. key_up: Publisher::new(),
  380. chr: Publisher::new(),
  381. mouse_btn_down: Publisher::new(),
  382. mouse_btn_up: Publisher::new(),
  383. mouse_move: Publisher::new(),
  384. mouse_wheel: Publisher::new(),
  385. touch: Publisher::new(),
  386. })
  387. }
  388. fn notify_resize(&self, screen_size: Dimension) {
  389. self.resize.notify(screen_size);
  390. }
  391. fn notify_key_down(&self, key: KeyCode, mods: KeyMods, repeat: bool) {
  392. let ev = (key, mods, repeat);
  393. self.key_down.notify(ev);
  394. }
  395. fn notify_key_up(&self, key: KeyCode, mods: KeyMods) {
  396. let ev = (key, mods);
  397. self.key_up.notify(ev);
  398. }
  399. fn notify_char(&self, chr: char, mods: KeyMods, repeat: bool) {
  400. let ev = (chr, mods, repeat);
  401. self.chr.notify(ev);
  402. }
  403. fn notify_mouse_btn_down(&self, button: MouseButton, mouse_pos: Point) {
  404. let ev = (button, mouse_pos);
  405. self.mouse_btn_down.notify(ev);
  406. }
  407. fn notify_mouse_btn_up(&self, button: MouseButton, mouse_pos: Point) {
  408. let ev = (button, mouse_pos);
  409. self.mouse_btn_up.notify(ev);
  410. }
  411. fn notify_mouse_move(&self, mouse_pos: Point) {
  412. self.mouse_move.notify(mouse_pos);
  413. }
  414. fn notify_mouse_wheel(&self, wheel_pos: Point) {
  415. self.mouse_wheel.notify(wheel_pos);
  416. }
  417. fn notify_touch(&self, phase: TouchPhase, id: u64, touch_pos: Point) {
  418. let ev = (phase, id, touch_pos);
  419. self.touch.notify(ev);
  420. }
  421. pub fn subscribe_resize(&self) -> Subscription<Dimension> {
  422. self.resize.clone().subscribe()
  423. }
  424. pub fn subscribe_key_down(&self) -> Subscription<(KeyCode, KeyMods, bool)> {
  425. self.key_down.clone().subscribe()
  426. }
  427. pub fn subscribe_key_up(&self) -> Subscription<(KeyCode, KeyMods)> {
  428. self.key_up.clone().subscribe()
  429. }
  430. pub fn subscribe_char(&self) -> Subscription<(char, KeyMods, bool)> {
  431. self.chr.clone().subscribe()
  432. }
  433. pub fn subscribe_mouse_btn_down(&self) -> Subscription<(MouseButton, Point)> {
  434. self.mouse_btn_down.clone().subscribe()
  435. }
  436. pub fn subscribe_mouse_btn_up(&self) -> Subscription<(MouseButton, Point)> {
  437. self.mouse_btn_up.clone().subscribe()
  438. }
  439. pub fn subscribe_mouse_move(&self) -> Subscription<Point> {
  440. self.mouse_move.clone().subscribe()
  441. }
  442. pub fn subscribe_mouse_wheel(&self) -> Subscription<Point> {
  443. self.mouse_wheel.clone().subscribe()
  444. }
  445. pub fn subscribe_touch(&self) -> Subscription<(TouchPhase, u64, Point)> {
  446. self.touch.clone().subscribe()
  447. }
  448. }
  449. struct Stage {
  450. #[allow(dead_code)]
  451. app: AppPtr,
  452. #[allow(dead_code)]
  453. async_runtime: AsyncRuntime,
  454. ctx: Box<dyn RenderingBackend>,
  455. pipeline: Pipeline,
  456. white_texture: miniquad::TextureId,
  457. draw_calls: HashMap<u64, DrawCall>,
  458. textures: HashMap<GfxTextureId, miniquad::TextureId>,
  459. buffers: HashMap<GfxBufferId, miniquad::BufferId>,
  460. method_rep: mpsc::Receiver<GraphicsMethod>,
  461. event_pub: GraphicsEventPublisherPtr,
  462. }
  463. impl Stage {
  464. pub fn new(
  465. app: AppPtr,
  466. async_runtime: AsyncRuntime,
  467. method_rep: mpsc::Receiver<GraphicsMethod>,
  468. event_pub: GraphicsEventPublisherPtr,
  469. cv_started: Arc<CondVar>,
  470. ) -> Self {
  471. let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();
  472. // This will start the app to start. Needed since we cannot get window size for init
  473. // until window is created.
  474. cv_started.notify();
  475. let white_texture = ctx.new_texture_from_rgba8(1, 1, &[255, 255, 255, 255]);
  476. let mut shader_meta: ShaderMeta = shader::meta();
  477. shader_meta.uniforms.uniforms.push(UniformDesc::new("Projection", UniformType::Mat4));
  478. shader_meta.uniforms.uniforms.push(UniformDesc::new("Model", UniformType::Mat4));
  479. let shader = ctx
  480. .new_shader(
  481. match ctx.info().backend {
  482. Backend::OpenGl => ShaderSource::Glsl {
  483. vertex: shader::GL_VERTEX,
  484. fragment: shader::GL_FRAGMENT,
  485. },
  486. Backend::Metal => ShaderSource::Msl { program: shader::METAL },
  487. },
  488. shader_meta,
  489. )
  490. .unwrap();
  491. let params = PipelineParams {
  492. color_blend: Some(BlendState::new(
  493. Equation::Add,
  494. BlendFactor::Value(BlendValue::SourceAlpha),
  495. BlendFactor::OneMinusValue(BlendValue::SourceAlpha),
  496. )),
  497. ..Default::default()
  498. };
  499. let pipeline = ctx.new_pipeline(
  500. &[BufferLayout::default()],
  501. &[
  502. VertexAttribute::new("in_pos", VertexFormat::Float2),
  503. VertexAttribute::new("in_color", VertexFormat::Float4),
  504. VertexAttribute::new("in_uv", VertexFormat::Float2),
  505. ],
  506. shader,
  507. params,
  508. );
  509. Stage {
  510. app,
  511. async_runtime,
  512. ctx,
  513. pipeline,
  514. white_texture,
  515. draw_calls: HashMap::from([(0, DrawCall { instrs: vec![], dcs: vec![], z_index: 0 })]),
  516. textures: HashMap::new(),
  517. buffers: HashMap::new(),
  518. method_rep,
  519. event_pub,
  520. }
  521. }
  522. fn process_method(&mut self, method: GraphicsMethod) {
  523. //debug!(target: "gfx", "Received method: {:?}", method);
  524. match method {
  525. GraphicsMethod::NewTexture((width, height, data, gfx_texture_id)) => {
  526. self.method_new_texture(width, height, data, gfx_texture_id)
  527. }
  528. GraphicsMethod::DeleteTexture(texture) => self.method_delete_texture(texture),
  529. GraphicsMethod::NewVertexBuffer((verts, sendr)) => {
  530. self.method_new_vertex_buffer(verts, sendr)
  531. }
  532. GraphicsMethod::NewIndexBuffer((indices, sendr)) => {
  533. self.method_new_index_buffer(indices, sendr)
  534. }
  535. GraphicsMethod::DeleteBuffer(buffer) => self.method_delete_buffer(buffer),
  536. GraphicsMethod::ReplaceDrawCalls(dcs) => self.method_replace_draw_calls(dcs),
  537. };
  538. }
  539. fn method_new_texture(
  540. &mut self,
  541. width: u16,
  542. height: u16,
  543. data: Vec<u8>,
  544. gfx_texture_id: GfxTextureId,
  545. ) {
  546. let texture = self.ctx.new_texture_from_rgba8(width, height, &data);
  547. if DEBUG_GFXAPI {
  548. debug!(target: "gfx", "Invoked method: new_texture({}, {}, ..., {}) -> {:?}",
  549. width, height, gfx_texture_id, texture);
  550. //debug!(target: "gfx", "Invoked method: new_texture({}, {}, ..., {}) -> {:?}\n{}",
  551. // width, height, gfx_texture_id, texture,
  552. // ansi_texture(width as usize, height as usize, &data));
  553. }
  554. self.textures.insert(gfx_texture_id, texture);
  555. }
  556. fn method_delete_texture(&mut self, gfx_texture_id: GfxTextureId) {
  557. let texture = self.textures.remove(&gfx_texture_id).expect("couldn't find gfx_texture_id");
  558. if DEBUG_GFXAPI {
  559. debug!(target: "gfx", "Invoked method: delete_texture({} => {:?})",
  560. gfx_texture_id, texture);
  561. }
  562. self.ctx.delete_texture(texture);
  563. }
  564. fn method_new_vertex_buffer(&mut self, verts: Vec<Vertex>, gfx_buffer_id: GfxBufferId) {
  565. let buffer = self.ctx.new_buffer(
  566. BufferType::VertexBuffer,
  567. BufferUsage::Immutable,
  568. BufferSource::slice(&verts),
  569. );
  570. if DEBUG_GFXAPI {
  571. debug!(target: "gfx", "Invoked method: new_vertex_buffer(..., {}) -> {:?}",
  572. gfx_buffer_id, buffer);
  573. //debug!(target: "gfx", "Invoked method: new_vertex_buffer({:?}, {}) -> {:?}",
  574. // verts, gfx_buffer_id, buffer);
  575. }
  576. self.buffers.insert(gfx_buffer_id, buffer);
  577. }
  578. fn method_new_index_buffer(&mut self, indices: Vec<u16>, gfx_buffer_id: GfxBufferId) {
  579. let buffer = self.ctx.new_buffer(
  580. BufferType::IndexBuffer,
  581. BufferUsage::Immutable,
  582. BufferSource::slice(&indices),
  583. );
  584. if DEBUG_GFXAPI {
  585. debug!(target: "gfx", "Invoked method: new_index_buffer({}) -> {:?}",
  586. gfx_buffer_id, buffer);
  587. //debug!(target: "gfx", "Invoked method: new_index_buffer({:?}, {}) -> {:?}",
  588. // indices, gfx_buffer_id, buffer);
  589. }
  590. self.buffers.insert(gfx_buffer_id, buffer);
  591. }
  592. fn method_delete_buffer(&mut self, gfx_buffer_id: GfxBufferId) {
  593. let buffer = self.buffers.remove(&gfx_buffer_id).expect("couldn't find gfx_buffer_id");
  594. if DEBUG_GFXAPI {
  595. debug!(target: "gfx", "Invoked method: delete_buffer({} => {:?})",
  596. gfx_buffer_id, buffer);
  597. }
  598. self.ctx.delete_buffer(buffer);
  599. }
  600. fn method_replace_draw_calls(&mut self, dcs: Vec<(u64, GfxDrawCall)>) {
  601. if DEBUG_GFXAPI {
  602. debug!(target: "gfx", "Invoked method: replace_draw_calls({:?})", dcs);
  603. }
  604. for (key, val) in dcs {
  605. let val = val.compile(&self.textures, &self.buffers);
  606. self.draw_calls.insert(key, val);
  607. }
  608. }
  609. }
  610. impl EventHandler for Stage {
  611. fn update(&mut self) {
  612. // Process as many methods as we can
  613. while let Ok(method) = self.method_rep.try_recv() {
  614. self.process_method(method);
  615. }
  616. }
  617. fn draw(&mut self) {
  618. self.ctx.begin_default_pass(PassAction::Nothing);
  619. self.ctx.apply_pipeline(&self.pipeline);
  620. // This will make the top left (0, 0) and the bottom right (1, 1)
  621. // Default is (-1, 1) -> (1, -1)
  622. let proj = glam::Mat4::from_translation(glam::Vec3::new(-1., 1., 0.)) *
  623. glam::Mat4::from_scale(glam::Vec3::new(2., -2., 1.));
  624. let mut uniforms_data = [0u8; 128];
  625. let data: [u8; 64] = unsafe { std::mem::transmute_copy(&proj) };
  626. uniforms_data[0..64].copy_from_slice(&data);
  627. //let data: [u8; 64] = unsafe { std::mem::transmute_copy(&model) };
  628. //uniforms_data[64..].copy_from_slice(&data);
  629. assert_eq!(128, 2 * UniformType::Mat4.size());
  630. let (screen_w, screen_h) = miniquad::window::screen_size();
  631. let mut render_ctx = RenderContext {
  632. ctx: &mut self.ctx,
  633. draw_calls: &self.draw_calls,
  634. uniforms_data,
  635. white_texture: self.white_texture,
  636. scale: 1.,
  637. view: Rectangle::from([0., 0., screen_w, screen_h]),
  638. cursor: Point::from([0., 0.]),
  639. };
  640. render_ctx.draw();
  641. self.ctx.commit_frame();
  642. }
  643. fn resize_event(&mut self, width: f32, height: f32) {
  644. self.event_pub.notify_resize(Dimension::from([width, height]));
  645. }
  646. fn key_down_event(&mut self, keycode: KeyCode, mods: KeyMods, repeat: bool) {
  647. debug!(target: "gfx", "key_down_event");
  648. self.event_pub.notify_key_down(keycode, mods, repeat);
  649. }
  650. fn key_up_event(&mut self, keycode: KeyCode, mods: KeyMods) {
  651. self.event_pub.notify_key_up(keycode, mods);
  652. }
  653. fn char_event(&mut self, chr: char, mods: KeyMods, repeat: bool) {
  654. self.event_pub.notify_char(chr, mods, repeat);
  655. }
  656. fn mouse_button_down_event(&mut self, button: MouseButton, x: f32, y: f32) {
  657. let pos = Point::from([x, y]);
  658. self.event_pub.notify_mouse_btn_down(button, pos);
  659. }
  660. fn mouse_button_up_event(&mut self, button: MouseButton, x: f32, y: f32) {
  661. let pos = Point::from([x, y]);
  662. self.event_pub.notify_mouse_btn_up(button, pos);
  663. }
  664. fn mouse_motion_event(&mut self, x: f32, y: f32) {
  665. let pos = Point::from([x, y]);
  666. self.event_pub.notify_mouse_move(pos);
  667. }
  668. fn mouse_wheel_event(&mut self, x: f32, y: f32) {
  669. let pos = Point::from([x, y]);
  670. self.event_pub.notify_mouse_wheel(pos);
  671. }
  672. /// The id corresponds to multi-touch. Multiple touch events have different ids.
  673. fn touch_event(&mut self, phase: TouchPhase, id: u64, x: f32, y: f32) {
  674. let pos = Point::from([x, y]);
  675. self.event_pub.notify_touch(phase, id, pos);
  676. }
  677. fn quit_requested_event(&mut self) {
  678. debug!(target: "gfx", "quit requested");
  679. // Doesn't work
  680. //miniquad::window::cancel_quit();
  681. //self.app.stop();
  682. //self.async_runtime.stop();
  683. }
  684. }
  685. pub fn run_gui(
  686. app: AppPtr,
  687. async_runtime: AsyncRuntime,
  688. method_rep: mpsc::Receiver<GraphicsMethod>,
  689. event_pub: GraphicsEventPublisherPtr,
  690. cv_started: Arc<CondVar>,
  691. ) {
  692. let mut conf = miniquad::conf::Conf {
  693. high_dpi: true,
  694. window_resizable: true,
  695. platform: miniquad::conf::Platform {
  696. linux_backend: miniquad::conf::LinuxBackend::WaylandWithX11Fallback,
  697. wayland_use_fallback_decorations: false,
  698. //blocking_event_loop: true,
  699. ..Default::default()
  700. },
  701. ..Default::default()
  702. };
  703. let metal = std::env::args().nth(1).as_deref() == Some("metal");
  704. conf.platform.apple_gfx_api =
  705. if metal { conf::AppleGfxApi::Metal } else { conf::AppleGfxApi::OpenGl };
  706. miniquad::start(conf, || {
  707. Box::new(Stage::new(app, async_runtime, method_rep, event_pub, cv_started))
  708. });
  709. }