glium/index/
mod.rs

1/*!
2In order to draw, you need to provide a way for the video card to know how to link primitives
3together.
4
5There are eleven types of primitives, each one with a corresponding struct:
6
7 - `PointsList`
8 - `LinesList`
9 - `LinesListAdjacency`
10 - `LineStrip`
11 - `LineStripAdjacency`
12 - `TrianglesList`
13 - `TrianglesListAdjacency`
14 - `TriangleStrip`
15 - `TriangleStripAdjacency`
16 - `TriangleFan`
17 - `Patches`
18
19There are two ways to specify the indices that must be used:
20
21 - Passing a reference to an `IndexBuffer`, which contains a list of indices.
22 - `NoIndices`, in which case the vertices will be used in the order in which they are in the
23   vertex buffer.
24
25## Multidraw indirect
26
27In addition to indices, you can also use **multidraw indirect** rendering.
28
29The idea is to put a list of things to render in a buffer, and pass that buffer to OpenGL.
30
31*/
32use crate::gl;
33use crate::ToGlEnum;
34use crate::CapabilitiesSource;
35use crate::version::Api;
36use crate::version::Version;
37
38use std::mem;
39
40use crate::buffer::BufferAnySlice;
41
42pub use self::buffer::{IndexBuffer, IndexBufferSlice, IndexBufferAny};
43pub use self::buffer::CreationError as BufferCreationError;
44pub use self::multidraw::{DrawCommandsNoIndicesBuffer, DrawCommandNoIndices};
45pub use self::multidraw::{DrawCommandsIndicesBuffer, DrawCommandIndices};
46
47mod buffer;
48mod multidraw;
49
50/// Describes a source of indices used for drawing.
51#[derive(Clone)]
52pub enum IndicesSource<'a> {
53    /// A buffer uploaded in video memory.
54    IndexBuffer {
55        /// The buffer.
56        buffer: BufferAnySlice<'a>,
57        /// Type of indices in the buffer.
58        data_type: IndexType,
59        /// Type of primitives contained in the vertex source.
60        primitives: PrimitiveType,
61    },
62
63    /// Use a multidraw indirect buffer without indices.
64    MultidrawArray {
65        /// The buffer.
66        buffer: BufferAnySlice<'a>,
67        /// Type of primitives contained in the vertex source.
68        primitives: PrimitiveType,
69    },
70
71    /// Use a multidraw indirect buffer with indices.
72    MultidrawElement {
73        /// The buffer of the commands.
74        commands: BufferAnySlice<'a>,
75        /// The buffer of the indices.
76        indices: BufferAnySlice<'a>,
77        /// Type of indices in the buffer.
78        data_type: IndexType,
79        /// Type of primitives contained in the vertex source.
80        primitives: PrimitiveType,
81    },
82
83    /// Don't use indices. Assemble primitives by using the order in which the vertices are in
84    /// the vertices source.
85    NoIndices {
86        /// Type of primitives contained in the vertex source.
87        primitives: PrimitiveType,
88    },
89}
90
91impl<'a> IndicesSource<'a> {
92    /// Returns the type of the primitives.
93    #[inline]
94    pub fn get_primitives_type(&self) -> PrimitiveType {
95        *match self {
96            IndicesSource::IndexBuffer { primitives, .. } => primitives,
97            IndicesSource::MultidrawArray { primitives, .. } => primitives,
98            IndicesSource::MultidrawElement { primitives, .. } => primitives,
99            IndicesSource::NoIndices { primitives } => primitives,
100        }
101    }
102}
103
104/// List of available primitives.
105///
106/// See [this page for a visual representation of each primitive
107/// type](https://msdn.microsoft.com/en-us/library/windows/desktop/bb205124%28v=vs.85%29.aspx).
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub enum PrimitiveType {
110    /// Each vertex is an individual point.
111    Points,
112
113    /// Vertices are grouped by chunks of two vertices. Each chunk represents a line.
114    LinesList,
115
116    /// Vertices are grouped by chunks of four vertices. The second and third vertices of each
117    /// chunk represents the line.
118    ///
119    /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
120    /// there is any.
121    /// The first vertex represents the vertex adjacent to the second vertex. The fourth vertex
122    /// represents the vertex adjacent to the third vertex.
123    LinesListAdjacency,
124
125    /// Each vertex (except the last one) forms a line with the next vertex.
126    ///
127    /// For example vertices 0 and 1 form a line, vertices 1 and 2 form a line, vertices 2 and 3
128    /// form a line, etc.
129    LineStrip,
130
131    /// Similar to `LineStrip`, but with an additional vertex at the beginning and at the end
132    /// that represent the vertices adjacent to the first and last ones.
133    ///
134    /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
135    /// there is any.
136    LineStripAdjacency,
137
138    /// Each vertex forms a line with the next vertex. The last vertex form a line with the first
139    /// one.
140    LineLoop,
141
142    /// Vertices are grouped by chunks of three vertices. Each chunk represents a triangle.
143    ///
144    /// The order of the vertices is important, as it determines whether the triangle will be
145    /// clockwise or counter-clockwise. See `BackfaceCulling` for more infos.
146    TrianglesList,
147
148    /// Vertices are grouped by chunks of six vertices. The first, third and fifth vertices
149    /// represent a triangle.
150    ///
151    /// The order of the vertices is important, as it determines whether the triangle will be
152    /// clockwise or counter-clockwise. See `BackfaceCulling` for more infos.
153    ///
154    /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
155    /// there is any.
156    /// The second vertex represents the vertex adjacent to the first and third vertices. The
157    /// fourth vertex represents the vertex adjacent to the third and fifth vertices. The sixth
158    /// vertex represents the vertex adjacent to the first and fifth vertices.
159    TrianglesListAdjacency,
160
161    /// Each vertex (except the first one and the last one) forms a triangle with the previous
162    /// and the next vertices.
163    ///
164    /// For example vertices `0, 1, 2` form a triangle, `1, 2, 3` form a triangle, `2, 3, 4` form a
165    /// triangle, `3, 4, 5` form a triangle, etc.
166    ///
167    /// Each uneven triangle is reversed so that all triangles are facing the same
168    /// direction.
169    TriangleStrip,
170
171    /// Each even vertex forms a triangle with vertices `n+2` and `n+4`.
172    ///
173    /// Each uneven vertex is adjacent to the previous and next ones.
174    /// Adjacency information doesn't do anything per-se, but is passed to the geometry shader if
175    /// there is any.
176    TriangleStripAdjacency,
177
178    /// Starting at the second vertex, each vertex forms a triangle with the next and the first
179    /// vertices.
180    ///
181    /// For example vertices `0, 1, 2` form a triangle, `0, 2, 3` form a triangle, `0, 3, 4` form a
182    /// triangle, `0, 4, 5` form a triangle, etc.
183    TriangleFan,
184
185    /// Vertices are grouped by chunks of `vertices_per_patch` vertices.
186    ///
187    /// This primitives type can only be used in conjunction with a tessellation shader. The
188    /// tessellation shader will indicate how each patch will be divided into lines or triangles.
189    Patches {
190        /// Number of vertices per patch.
191        vertices_per_patch: u16,
192    },
193}
194
195impl PrimitiveType {
196    /// Returns true if the backend supports this type of primitives.
197    pub fn is_supported<C: ?Sized>(&self, caps: &C) -> bool where C: CapabilitiesSource {
198        match self {
199            &PrimitiveType::Points | &PrimitiveType::LinesList | &PrimitiveType::LineStrip |
200            &PrimitiveType::LineLoop | &PrimitiveType::TrianglesList |
201            &PrimitiveType::TriangleStrip | &PrimitiveType::TriangleFan => true,
202
203            &PrimitiveType::LinesListAdjacency | &PrimitiveType::LineStripAdjacency |
204            &PrimitiveType::TrianglesListAdjacency | &PrimitiveType::TriangleStripAdjacency => {
205                caps.get_version() >= &Version(Api::Gl, 3, 0) ||
206                caps.get_extensions().gl_arb_geometry_shader4 ||
207                caps.get_extensions().gl_ext_geometry_shader4 ||
208                caps.get_extensions().gl_ext_geometry_shader
209            },
210
211            &PrimitiveType::Patches { .. } => {
212                caps.get_version() >= &Version(Api::Gl, 4, 0) ||
213                caps.get_extensions().gl_arb_tessellation_shader
214            },
215        }
216    }
217}
218
219impl ToGlEnum for PrimitiveType {
220    #[inline]
221    fn to_glenum(&self) -> gl::types::GLenum {
222        match self {
223            PrimitiveType::Points => gl::POINTS,
224            PrimitiveType::LinesList => gl::LINES,
225            PrimitiveType::LinesListAdjacency => gl::LINES_ADJACENCY,
226            PrimitiveType::LineStrip => gl::LINE_STRIP,
227            PrimitiveType::LineStripAdjacency => gl::LINE_STRIP_ADJACENCY,
228            PrimitiveType::LineLoop => gl::LINE_LOOP,
229            PrimitiveType::TrianglesList => gl::TRIANGLES,
230            PrimitiveType::TrianglesListAdjacency => gl::TRIANGLES_ADJACENCY,
231            PrimitiveType::TriangleStrip => gl::TRIANGLE_STRIP,
232            PrimitiveType::TriangleStripAdjacency => gl::TRIANGLE_STRIP_ADJACENCY,
233            PrimitiveType::TriangleFan => gl::TRIANGLE_FAN,
234            PrimitiveType::Patches { .. } => gl::PATCHES,
235        }
236    }
237}
238
239/// Marker that can be used as an indices source when you don't need indices.
240///
241/// If you use this, then the primitives will be constructed using the order in which the
242/// vertices are in the vertices sources.
243#[derive(Copy, Clone, Debug)]
244pub struct NoIndices(pub PrimitiveType);
245
246impl<'a> From<NoIndices> for IndicesSource<'a> {
247    #[inline]
248    fn from(marker: NoIndices) -> IndicesSource<'a> {
249        IndicesSource::NoIndices {
250            primitives: marker.0
251        }
252    }
253}
254
255impl<'a, 'b> From<&'b NoIndices> for IndicesSource<'a> {
256    #[inline]
257    fn from(marker: &'b NoIndices) -> IndicesSource<'a> {
258        IndicesSource::NoIndices {
259            primitives: marker.0
260        }
261    }
262}
263
264/// Type of the indices in an index source.
265#[derive(Debug, Clone, Copy, PartialEq, Eq)]
266#[repr(u32)]    // GLenum
267pub enum IndexType {
268    /// u8
269    U8 = gl::UNSIGNED_BYTE,
270    /// u16
271    U16 = gl::UNSIGNED_SHORT,
272    /// u32
273    U32 = gl::UNSIGNED_INT,
274}
275
276impl IndexType {
277    /// Returns the size in bytes of each index of this type.
278    #[inline]
279    pub fn get_size(&self) -> usize {
280        match self {
281            IndexType::U8 => mem::size_of::<u8>(),
282            IndexType::U16 => mem::size_of::<u16>(),
283            IndexType::U32 => mem::size_of::<u32>(),
284        }
285    }
286
287    /// Returns true if the backend supports this type of index.
288    #[inline]
289    pub fn is_supported<C: ?Sized>(&self, caps: &C) -> bool where C: CapabilitiesSource {
290        match self {
291            IndexType::U8 => true,
292            IndexType::U16 => true,
293            IndexType::U32 => {
294                caps.get_version() >= &Version(Api::Gl, 1, 0) ||
295                caps.get_version() >= &Version(Api::GlEs, 3, 0) ||
296                caps.get_extensions().gl_oes_element_index_uint
297            },
298        }
299    }
300}
301
302impl ToGlEnum for IndexType {
303    #[inline]
304    fn to_glenum(&self) -> gl::types::GLenum {
305        *self as gl::types::GLenum
306    }
307}
308
309/// An index from the index buffer.
310pub unsafe trait Index: Copy + Send + 'static {
311    /// Returns the `IndexType` corresponding to this type.
312    fn get_type() -> IndexType;
313
314    /// Returns true if this type of index is supported by the backend.
315    fn is_supported<C: ?Sized>(caps: &C) -> bool where C: CapabilitiesSource {
316        Self::get_type().is_supported(caps)
317    }
318}
319
320unsafe impl Index for u8 {
321    #[inline]
322    fn get_type() -> IndexType {
323        IndexType::U8
324    }
325}
326
327unsafe impl Index for u16 {
328    #[inline]
329    fn get_type() -> IndexType {
330        IndexType::U16
331    }
332}
333
334unsafe impl Index for u32 {
335    #[inline]
336    fn get_type() -> IndexType {
337        IndexType::U32
338    }
339}