use std::iter::Chain;
use std::option::IntoIter;
pub use self::buffer::{VertexBuffer, VertexBufferAny};
pub use self::buffer::VertexBufferSlice;
pub use self::buffer::CreationError as BufferCreationError;
pub use self::format::{AttributeType, VertexFormat};
pub use self::transform_feedback::{is_transform_feedback_supported, TransformFeedbackSession};
use crate::buffer::BufferAnySlice;
use crate::CapabilitiesSource;
mod buffer;
mod format;
mod transform_feedback;
#[derive(Clone)]
pub enum VerticesSource<'a> {
VertexBuffer(BufferAnySlice<'a>, VertexFormat, bool),
Marker {
len: usize,
per_instance: bool,
},
}
pub struct EmptyVertexAttributes {
pub len: usize,
}
impl<'a> From<EmptyVertexAttributes> for VerticesSource<'a> {
#[inline]
fn from(this: EmptyVertexAttributes) -> VerticesSource<'a> {
VerticesSource::Marker { len: this.len, per_instance: false }
}
}
pub struct EmptyInstanceAttributes {
pub len: usize,
}
impl<'a> From<EmptyInstanceAttributes> for VerticesSource<'a> {
#[inline]
fn from(this: EmptyInstanceAttributes) -> VerticesSource<'a> {
VerticesSource::Marker { len: this.len, per_instance: true }
}
}
pub struct PerInstance<'a>(BufferAnySlice<'a>, VertexFormat);
impl<'a> From<PerInstance<'a>> for VerticesSource<'a> {
#[inline]
fn from(this: PerInstance<'a>) -> VerticesSource<'a> {
VerticesSource::VertexBuffer(this.0, this.1, true)
}
}
pub trait MultiVerticesSource<'a> {
type Iterator: Iterator<Item = VerticesSource<'a>>;
fn iter(self) -> Self::Iterator;
}
impl<'a, T> MultiVerticesSource<'a> for T
where T: Into<VerticesSource<'a>>
{
type Iterator = IntoIter<VerticesSource<'a>>;
#[inline]
fn iter(self) -> IntoIter<VerticesSource<'a>> {
Some(self.into()).into_iter()
}
}
macro_rules! impl_for_tuple {
($t:ident) => (
impl<'a, $t> MultiVerticesSource<'a> for ($t,)
where $t: Into<VerticesSource<'a>>
{
type Iterator = IntoIter<VerticesSource<'a>>;
#[inline]
fn iter(self) -> IntoIter<VerticesSource<'a>> {
Some(self.0.into()).into_iter()
}
}
);
($t1:ident, $t2:ident) => (
#[allow(non_snake_case)]
impl<'a, $t1, $t2> MultiVerticesSource<'a> for ($t1, $t2)
where $t1: Into<VerticesSource<'a>>, $t2: Into<VerticesSource<'a>>
{
type Iterator = Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
<($t2,) as MultiVerticesSource<'a>>::Iterator>;
#[inline]
fn iter(self) -> Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
<($t2,) as MultiVerticesSource<'a>>::Iterator>
{
let ($t1, $t2) = self;
Some($t1.into()).into_iter().chain(($t2,).iter())
}
}
impl_for_tuple!($t2);
);
($t1:ident, $($t2:ident),+) => (
#[allow(non_snake_case)]
impl<'a, $t1, $($t2),+> MultiVerticesSource<'a> for ($t1, $($t2),+)
where $t1: Into<VerticesSource<'a>>, $($t2: Into<VerticesSource<'a>>),+
{
type Iterator = Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
<($($t2),+) as MultiVerticesSource<'a>>::Iterator>;
#[inline]
fn iter(self) -> Chain<<($t1,) as MultiVerticesSource<'a>>::Iterator,
<($($t2),+) as MultiVerticesSource<'a>>::Iterator>
{
let ($t1, $($t2),+) = self;
Some($t1.into()).into_iter().chain(($($t2),+).iter())
}
}
impl_for_tuple!($($t2),+);
);
}
impl_for_tuple!(A, B, C, D, E, F, G);
pub trait Vertex: Copy + Sized {
fn build_bindings() -> VertexFormat;
fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
let format = Self::build_bindings();
for &(_, _, _, ref ty, _) in format.iter() {
if !ty.is_supported(caps) {
return false;
}
}
true
}
}
pub unsafe trait Attribute: Sized {
const TYPE: AttributeType;
#[inline]
fn get_type() -> AttributeType {
Self::TYPE
}
#[inline]
fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
Self::get_type().is_supported(caps)
}
}