use crate::gl;
use crate::ToGlEnum;
use crate::CapabilitiesSource;
use crate::version::Api;
use crate::version::Version;
use std::mem;
use crate::buffer::BufferAnySlice;
pub use self::buffer::{IndexBuffer, IndexBufferSlice, IndexBufferAny};
pub use self::buffer::CreationError as BufferCreationError;
pub use self::multidraw::{DrawCommandsNoIndicesBuffer, DrawCommandNoIndices};
pub use self::multidraw::{DrawCommandsIndicesBuffer, DrawCommandIndices};
mod buffer;
mod multidraw;
#[derive(Clone)]
pub enum IndicesSource<'a> {
IndexBuffer {
buffer: BufferAnySlice<'a>,
data_type: IndexType,
primitives: PrimitiveType,
},
MultidrawArray {
buffer: BufferAnySlice<'a>,
primitives: PrimitiveType,
},
MultidrawElement {
commands: BufferAnySlice<'a>,
indices: BufferAnySlice<'a>,
data_type: IndexType,
primitives: PrimitiveType,
},
NoIndices {
primitives: PrimitiveType,
},
}
impl<'a> IndicesSource<'a> {
#[inline]
pub fn get_primitives_type(&self) -> PrimitiveType {
*match self {
IndicesSource::IndexBuffer { primitives, .. } => primitives,
IndicesSource::MultidrawArray { primitives, .. } => primitives,
IndicesSource::MultidrawElement { primitives, .. } => primitives,
IndicesSource::NoIndices { primitives } => primitives,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PrimitiveType {
Points,
LinesList,
LinesListAdjacency,
LineStrip,
LineStripAdjacency,
LineLoop,
TrianglesList,
TrianglesListAdjacency,
TriangleStrip,
TriangleStripAdjacency,
TriangleFan,
Patches {
vertices_per_patch: u16,
},
}
impl PrimitiveType {
pub fn is_supported<C: ?Sized>(&self, caps: &C) -> bool where C: CapabilitiesSource {
match self {
&PrimitiveType::Points | &PrimitiveType::LinesList | &PrimitiveType::LineStrip |
&PrimitiveType::LineLoop | &PrimitiveType::TrianglesList |
&PrimitiveType::TriangleStrip | &PrimitiveType::TriangleFan => true,
&PrimitiveType::LinesListAdjacency | &PrimitiveType::LineStripAdjacency |
&PrimitiveType::TrianglesListAdjacency | &PrimitiveType::TriangleStripAdjacency => {
caps.get_version() >= &Version(Api::Gl, 3, 0) ||
caps.get_extensions().gl_arb_geometry_shader4 ||
caps.get_extensions().gl_ext_geometry_shader4 ||
caps.get_extensions().gl_ext_geometry_shader
},
&PrimitiveType::Patches { .. } => {
caps.get_version() >= &Version(Api::Gl, 4, 0) ||
caps.get_extensions().gl_arb_tessellation_shader
},
}
}
}
impl ToGlEnum for PrimitiveType {
#[inline]
fn to_glenum(&self) -> gl::types::GLenum {
match self {
PrimitiveType::Points => gl::POINTS,
PrimitiveType::LinesList => gl::LINES,
PrimitiveType::LinesListAdjacency => gl::LINES_ADJACENCY,
PrimitiveType::LineStrip => gl::LINE_STRIP,
PrimitiveType::LineStripAdjacency => gl::LINE_STRIP_ADJACENCY,
PrimitiveType::LineLoop => gl::LINE_LOOP,
PrimitiveType::TrianglesList => gl::TRIANGLES,
PrimitiveType::TrianglesListAdjacency => gl::TRIANGLES_ADJACENCY,
PrimitiveType::TriangleStrip => gl::TRIANGLE_STRIP,
PrimitiveType::TriangleStripAdjacency => gl::TRIANGLE_STRIP_ADJACENCY,
PrimitiveType::TriangleFan => gl::TRIANGLE_FAN,
PrimitiveType::Patches { .. } => gl::PATCHES,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct NoIndices(pub PrimitiveType);
impl<'a> From<NoIndices> for IndicesSource<'a> {
#[inline]
fn from(marker: NoIndices) -> IndicesSource<'a> {
IndicesSource::NoIndices {
primitives: marker.0
}
}
}
impl<'a, 'b> From<&'b NoIndices> for IndicesSource<'a> {
#[inline]
fn from(marker: &'b NoIndices) -> IndicesSource<'a> {
IndicesSource::NoIndices {
primitives: marker.0
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u32)] pub enum IndexType {
U8 = gl::UNSIGNED_BYTE,
U16 = gl::UNSIGNED_SHORT,
U32 = gl::UNSIGNED_INT,
}
impl IndexType {
#[inline]
pub fn get_size(&self) -> usize {
match self {
IndexType::U8 => mem::size_of::<u8>(),
IndexType::U16 => mem::size_of::<u16>(),
IndexType::U32 => mem::size_of::<u32>(),
}
}
#[inline]
pub fn is_supported<C: ?Sized>(&self, caps: &C) -> bool where C: CapabilitiesSource {
match self {
IndexType::U8 => true,
IndexType::U16 => true,
IndexType::U32 => {
caps.get_version() >= &Version(Api::Gl, 1, 0) ||
caps.get_version() >= &Version(Api::GlEs, 3, 0) ||
caps.get_extensions().gl_oes_element_index_uint
},
}
}
}
impl ToGlEnum for IndexType {
#[inline]
fn to_glenum(&self) -> gl::types::GLenum {
*self as gl::types::GLenum
}
}
pub unsafe trait Index: Copy + Send + 'static {
fn get_type() -> IndexType;
fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
Self::get_type().is_supported(caps)
}
}
unsafe impl Index for u8 {
#[inline]
fn get_type() -> IndexType {
IndexType::U8
}
}
unsafe impl Index for u16 {
#[inline]
fn get_type() -> IndexType {
IndexType::U16
}
}
unsafe impl Index for u32 {
#[inline]
fn get_type() -> IndexType {
IndexType::U32
}
}