buffers: refactor locking structure for higher fps and automatic surface commit
This commit is contained in:
		| @@ -1,15 +1,12 @@ | |||||||
| use crate::events::EventBus; |  | ||||||
| use crate::geometry::*; | use crate::geometry::*; | ||||||
| use crate::lib8::interpolate::Fract8Ops; | use crate::lib8::interpolate::Fract8Ops; | ||||||
| use crate::power::AsMilliwatts; | use crate::power::AsMilliwatts; | ||||||
| use crate::render::{PixelView, Sample, Shader, Surface, Surfaces, HardwarePixel}; | use crate::render::{PixelView, Sample, Shader, Surface, Surfaces, HardwarePixel}; | ||||||
| use crate::task::Task; |  | ||||||
|  |  | ||||||
| use std::fmt::Debug; | use std::cell::RefCell; | ||||||
| use std::ops::IndexMut; | use std::ops::IndexMut; | ||||||
|  |  | ||||||
| use std::sync::atomic::AtomicBool; | use std::sync::atomic::AtomicBool; | ||||||
| use std::sync::RwLock; |  | ||||||
| use std::sync::{Arc, Mutex}; | use std::sync::{Arc, Mutex}; | ||||||
|  |  | ||||||
| struct ShaderBinding { | struct ShaderBinding { | ||||||
| @@ -80,9 +77,9 @@ impl Surface for BufferedSurface { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn set_shader(&mut self, shader: Box<dyn Shader>) { |     fn set_shader<T: Shader + 'static>(&mut self, shader: T) { | ||||||
|         self.updater.push(SurfaceUpdate { |         self.updater.push(SurfaceUpdate { | ||||||
|             shader: Some(Some(shader)), |             shader: Some(Some(Box::new(shader))), | ||||||
|             slot: self.slot, |             slot: self.slot, | ||||||
|             ..Default::default() |             ..Default::default() | ||||||
|         }); |         }); | ||||||
| @@ -143,6 +140,7 @@ impl ShaderChain { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn commit(&mut self) { |     pub fn commit(&mut self) { | ||||||
|  |         if self.is_dirty() { | ||||||
|             let mut queue: Vec<SurfaceUpdate> = { |             let mut queue: Vec<SurfaceUpdate> = { | ||||||
|                 let mut updates = self.updates.pending.lock().unwrap(); |                 let mut updates = self.updates.pending.lock().unwrap(); | ||||||
|                 std::mem::take(updates.as_mut()) |                 std::mem::take(updates.as_mut()) | ||||||
| @@ -163,11 +161,7 @@ impl ShaderChain { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| impl Surfaces for ShaderChain { |     fn new_surface(&mut self, area: Rectangle<Virtual>) -> Result<BufferedSurface, ()> { | ||||||
|     type Error = (); |  | ||||||
|     type Surface = BufferedSurface; |  | ||||||
|  |  | ||||||
|     fn new_surface(&mut self, area: Rectangle<Virtual>) -> Result<Self::Surface, Self::Error> { |  | ||||||
|         let next_slot = self.bindings.len(); |         let next_slot = self.bindings.len(); | ||||||
|         self.bindings.push(ShaderBinding { |         self.bindings.push(ShaderBinding { | ||||||
|             opacity: 255, |             opacity: 255, | ||||||
| @@ -182,12 +176,12 @@ impl Surfaces for ShaderChain { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn render_to<S: Sample>(&self, output: &mut S, frame: usize) { |     fn render_to<S: Sample>(&self, output: &mut S, frame: usize) { | ||||||
|         for surface in self.bindings.iter() { |         for surface in &self.bindings { | ||||||
|             let opacity = surface.opacity; |             let opacity = surface.opacity; | ||||||
|             if opacity > 0 { |             if opacity > 0 { | ||||||
|  |                 if let Some(ref shader) = surface.shader { | ||||||
|                     let rect = surface.rect; |                     let rect = surface.rect; | ||||||
|                     let mut sample = output.sample(&rect); |                     let mut sample = output.sample(&rect); | ||||||
|                 if let Some(ref shader) = surface.shader { |  | ||||||
|                     while let Some((virt_coords, pixel)) = sample.next() { |                     while let Some((virt_coords, pixel)) = sample.next() { | ||||||
|                         *pixel = pixel.blend8(shader.draw(&virt_coords, frame).into(), opacity); |                         *pixel = pixel.blend8(shader.draw(&virt_coords, frame).into(), opacity); | ||||||
|                     } |                     } | ||||||
| @@ -197,37 +191,29 @@ impl Surfaces for ShaderChain { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Clone)] |  | ||||||
| pub struct BufferedSurfacePool { | pub struct BufferedSurfacePool { | ||||||
|     pool: Arc<RwLock<ShaderChain>> |     pool: RefCell<ShaderChain> | ||||||
| } | } | ||||||
|  |  | ||||||
| impl BufferedSurfacePool { | impl BufferedSurfacePool { | ||||||
|     pub fn new() -> Self { |     pub fn new() -> Self { | ||||||
|         BufferedSurfacePool { |         BufferedSurfacePool { | ||||||
|             pool: Arc::new(RwLock::new(ShaderChain::new())) |             pool: RefCell::new(ShaderChain::new()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Surfaces for BufferedSurfacePool { | impl Surfaces for BufferedSurfacePool { | ||||||
|     type Error = (); |     type Error = (); | ||||||
|     type Surface = <ShaderChain as Surfaces>::Surface; |     type Surface = BufferedSurface; | ||||||
|     fn new_surface(&mut self, area: crate::geometry::Rectangle<crate::geometry::Virtual>) -> Result<Self::Surface, Self::Error> { |     fn new_surface(&mut self, area: crate::geometry::Rectangle<crate::geometry::Virtual>) -> Result<Self::Surface, Self::Error> { | ||||||
|         self.pool.write().unwrap().new_surface(area) |         self.pool.borrow_mut().new_surface(area) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     fn render_to<S: crate::render::Sample>(&self, output: &mut S, frame: usize) { |     fn render_to<S: crate::render::Sample>(&self, output: &mut S, frame: usize) { | ||||||
|         self.pool.read().unwrap().render_to(output, frame); |         let mut b = self.pool.borrow_mut(); | ||||||
|     } |         b.commit(); | ||||||
| } |         b.render_to(output, frame); | ||||||
|  |  | ||||||
|  |  | ||||||
| impl Task for BufferedSurfacePool { |  | ||||||
|     fn on_tick(&mut self, _bus: &mut EventBus) { |  | ||||||
|         if self.pool.read().unwrap().is_dirty() { |  | ||||||
|             self.pool.write().unwrap().commit(); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user