buffers: refactor locking structure for higher fps and automatic surface commit
This commit is contained in:
parent
9c773f0335
commit
3a49e7e390
@ -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,31 +140,28 @@ impl ShaderChain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn commit(&mut self) {
|
pub fn commit(&mut self) {
|
||||||
let mut queue: Vec<SurfaceUpdate> = {
|
if self.is_dirty() {
|
||||||
let mut updates = self.updates.pending.lock().unwrap();
|
let mut queue: Vec<SurfaceUpdate> = {
|
||||||
std::mem::take(updates.as_mut())
|
let mut updates = self.updates.pending.lock().unwrap();
|
||||||
};
|
std::mem::take(updates.as_mut())
|
||||||
for update in queue.iter_mut() {
|
};
|
||||||
let target_slot = &mut self.bindings[update.slot];
|
for update in queue.iter_mut() {
|
||||||
if let Some(shader) = update.shader.take() {
|
let target_slot = &mut self.bindings[update.slot];
|
||||||
target_slot.shader = shader;
|
if let Some(shader) = update.shader.take() {
|
||||||
}
|
target_slot.shader = shader;
|
||||||
if let Some(opacity) = update.opacity.take() {
|
}
|
||||||
target_slot.opacity = opacity;
|
if let Some(opacity) = update.opacity.take() {
|
||||||
}
|
target_slot.opacity = opacity;
|
||||||
if let Some(rect) = update.rect.take() {
|
}
|
||||||
target_slot.rect = rect;
|
if let Some(rect) = update.rect.take() {
|
||||||
|
target_slot.rect = rect;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
self.updates.damaged.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
self.updates.damaged.store(false, std::sync::atomic::Ordering::Relaxed);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
||||||
let rect = surface.rect;
|
|
||||||
let mut sample = output.sample(&rect);
|
|
||||||
if let Some(ref shader) = surface.shader {
|
if let Some(ref shader) = surface.shader {
|
||||||
|
let rect = surface.rect;
|
||||||
|
let mut sample = output.sample(&rect);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user