use crate::action::*;
use metal;
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct PipelineConfiguration {
pub sample_count: u64,
pub pixel_format: metal::MTLPixelFormat,
pub blend_mode: BlendMode,
pub vertex_shader: String,
pub fragment_shader: String
}
impl Default for PipelineConfiguration {
fn default() -> PipelineConfiguration {
PipelineConfiguration {
sample_count: 1,
pixel_format: metal::MTLPixelFormat::BGRA8Unorm,
blend_mode: BlendMode::SourceOver,
vertex_shader: String::from("simple_vertex"),
fragment_shader: String::from("simple_fragment")
}
}
}
impl PipelineConfiguration {
pub fn for_texture(texture: &metal::Texture) -> PipelineConfiguration {
let mut pipeline_config = Self::default();
pipeline_config.update_for_texture(texture);
pipeline_config
}
pub fn update_for_texture(&mut self, texture: &metal::Texture) {
self.sample_count = texture.sample_count();
self.pixel_format = texture.pixel_format();
}
pub fn to_pipeline_state(&self, device: &metal::Device, library: &metal::Library) -> metal::RenderPipelineState {
let descriptor = metal::RenderPipelineDescriptor::new();
let vertex_shader = library.get_function(&self.vertex_shader, None).unwrap();
let fragment_shader = library.get_function(&self.fragment_shader, None).unwrap();
descriptor.set_vertex_function(Some(&vertex_shader));
descriptor.set_fragment_function(Some(&fragment_shader));
descriptor.set_sample_count(self.sample_count);
use self::BlendMode::*;
use metal::MTLBlendFactor::{SourceAlpha, OneMinusSourceAlpha, One, DestinationAlpha, OneMinusDestinationAlpha, Zero, OneMinusSourceColor, OneMinusDestinationColor};
let (src_rgb, dst_rgb, src_alpha, dst_alpha) = match self.blend_mode {
SourceOver => (SourceAlpha, OneMinusSourceAlpha, One, OneMinusSourceAlpha),
DestinationOver => (OneMinusDestinationAlpha, DestinationAlpha, OneMinusDestinationAlpha, One),
SourceIn => (DestinationAlpha, Zero, DestinationAlpha, Zero),
DestinationIn => (Zero, SourceAlpha, Zero, SourceAlpha),
SourceOut => (Zero, OneMinusDestinationAlpha, Zero, OneMinusDestinationAlpha),
DestinationOut => (Zero, OneMinusSourceAlpha, Zero, OneMinusSourceAlpha),
SourceATop => (OneMinusDestinationAlpha, SourceAlpha, OneMinusDestinationAlpha, SourceAlpha),
DestinationATop => (OneMinusDestinationAlpha, OneMinusSourceAlpha, OneMinusDestinationAlpha, OneMinusSourceAlpha),
AllChannelAlphaSourceOver => (One, OneMinusSourceColor, One, OneMinusSourceAlpha),
AllChannelAlphaDestinationOver => (OneMinusDestinationColor, One, OneMinusDestinationAlpha, One)
};
descriptor.color_attachments().object_at(0).unwrap().set_pixel_format(self.pixel_format);
descriptor.color_attachments().object_at(0).unwrap().set_blending_enabled(true);
descriptor.color_attachments().object_at(0).unwrap().set_source_rgb_blend_factor(src_rgb);
descriptor.color_attachments().object_at(0).unwrap().set_destination_rgb_blend_factor(dst_rgb);
descriptor.color_attachments().object_at(0).unwrap().set_source_alpha_blend_factor(src_alpha);
descriptor.color_attachments().object_at(0).unwrap().set_destination_alpha_blend_factor(dst_alpha);
device.new_render_pipeline_state(&descriptor).unwrap()
}
}