use fnv::FnvHashMap as HashMap;
use crate::{
error::Result,
types::{DepthStencilView, Encoder, Factory, RenderTargetView, ShaderResourceView, Window},
};
#[derive(Clone, Debug, PartialEq)]
pub struct ColorBuffer {
pub as_input: Option<ShaderResourceView<[f32; 4]>>,
pub as_output: RenderTargetView,
}
#[derive(Clone, Debug, PartialEq)]
pub struct DepthBuffer {
pub as_input: Option<ShaderResourceView<f32>>,
pub as_output: DepthStencilView,
}
pub type Targets = HashMap<String, Target>;
#[derive(Clone, Debug, PartialEq)]
pub struct Target {
color_bufs: Vec<ColorBuffer>,
depth_buf: Option<DepthBuffer>,
size: (u32, u32),
}
impl Target {
pub(crate) fn new(cb: ColorBuffer, db: DepthBuffer, size: (u32, u32)) -> Self {
Target {
color_bufs: vec![cb],
depth_buf: Some(db),
size,
}
}
pub fn named<N: Into<String>>(name: N) -> TargetBuilder {
TargetBuilder::new(name)
}
pub fn clear_color<V: Into<[f32; 4]>>(&self, enc: &mut Encoder, value: V) {
let val = value.into();
for buf in self.color_bufs.iter() {
enc.clear(&buf.as_output, val);
}
}
pub fn clear_depth_stencil<V: Into<f32>>(&self, enc: &mut Encoder, value: V) {
if let Some(ref buf) = self.depth_buf {
let val = value.into();
enc.clear_depth(&buf.as_output, val);
enc.clear_stencil(&buf.as_output, val as u8);
}
}
pub fn size(&self) -> (u32, u32) {
self.size
}
pub fn color_buf(&self, i: usize) -> Option<&ColorBuffer> {
self.color_bufs.get(i)
}
pub fn color_bufs(&self) -> &[ColorBuffer] {
self.color_bufs.as_ref()
}
pub fn depth_buf(&self) -> Option<&DepthBuffer> {
self.depth_buf.as_ref()
}
#[cfg(all(feature = "d3d11", target_os = "windows"))]
pub fn resize_main_target(window: &Window) -> Result<(Device, Factory, Target)> {
unimplemented!()
}
#[cfg(all(feature = "metal", target_os = "macos"))]
pub fn resize_main_target(window: &Window) -> Result<(Device, Factory, Target)> {
unimplemented!()
}
#[cfg(feature = "opengl")]
pub fn resize_main_target(&mut self, window: &Window) {
if let Some(depth_buf) = self.depth_buf.as_mut() {
for color_buf in &mut self.color_bufs {
use gfx_window_glutin as win;
win::update_views(window, &mut color_buf.as_output, &mut depth_buf.as_output);
}
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct TargetBuilder {
custom_size: Option<(u32, u32)>,
name: String,
has_depth_buf: bool,
num_color_bufs: usize,
}
impl TargetBuilder {
pub fn new<S: Into<String>>(name: S) -> Self {
TargetBuilder {
custom_size: None,
name: name.into(),
has_depth_buf: false,
num_color_bufs: 1,
}
}
pub fn with_depth_buf(mut self, has_buf: bool) -> Self {
self.has_depth_buf = has_buf;
self
}
pub fn with_num_color_bufs(mut self, num: usize) -> Self {
self.num_color_bufs = num;
self
}
pub fn with_size(mut self, size: (u32, u32)) -> Self {
self.custom_size = Some(size);
self
}
pub(crate) fn build(self, fac: &mut Factory, size: (u32, u32)) -> Result<(String, Target)> {
use gfx::Factory;
let size = self.custom_size.unwrap_or(size);
let color_bufs = (0..self.num_color_bufs)
.map(|_| {
let (w, h) = (size.0 as u16, size.1 as u16);
let (_, res, rt) = fac.create_render_target(w, h)?;
Ok(ColorBuffer {
as_input: Some(res),
as_output: rt,
})
})
.collect::<Result<_>>()?;
let depth_buf = if self.has_depth_buf {
let (w, h) = (size.0 as u16, size.1 as u16);
let (_, res, dt) = fac.create_depth_stencil(w, h)?;
let depth = DepthBuffer {
as_input: Some(res),
as_output: dt,
};
Some(depth)
} else {
None
};
let target = Target {
color_bufs,
depth_buf,
size,
};
Ok((self.name, target))
}
}