glium/index/
buffer.rs

1use crate::buffer::{Buffer, BufferSlice, BufferMutSlice, BufferAny, BufferType};
2use crate::buffer::{BufferMode, BufferCreationError};
3use crate::gl;
4use crate::GlObject;
5
6use crate::backend::Facade;
7
8use crate::index::IndicesSource;
9use crate::index::Index;
10use crate::index::IndexType;
11use crate::index::PrimitiveType;
12
13use std::ops::{Deref, DerefMut};
14use std::fmt;
15use std::error::Error;
16use crate::utils::range::RangeArgument;
17
18/// Error that can happen while creating an index buffer.
19#[derive(Debug, Copy, Clone)]
20pub enum CreationError {
21    /// The type of index is not supported by the backend.
22    IndexTypeNotSupported,
23
24    /// The type of primitives is not supported by the backend.
25    PrimitiveTypeNotSupported,
26
27    /// An error happened while creating the buffer.
28    BufferCreationError(BufferCreationError),
29}
30
31impl fmt::Display for CreationError {
32    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
33        use self::CreationError::*;
34        let desc = match *self {
35            IndexTypeNotSupported =>
36                "The type of index is not supported by the backend",
37            PrimitiveTypeNotSupported =>
38                "The type of primitives is not supported by the backend",
39            BufferCreationError(_) =>
40                "An error happened while creating the buffer",
41        };
42        fmt.write_str(desc)
43    }
44}
45
46impl Error for CreationError {
47    fn source(&self) -> Option<&(dyn Error + 'static)> {
48        use self::CreationError::*;
49        match *self {
50            BufferCreationError(ref err) => Some(err),
51            _ => None,
52        }
53    }
54}
55
56impl From<BufferCreationError> for CreationError {
57    #[inline]
58    fn from(err: BufferCreationError) -> CreationError {
59        CreationError::BufferCreationError(err)
60    }
61}
62
63/// A list of indices loaded in the graphics card's memory.
64#[derive(Debug)]
65pub struct IndexBuffer<T> where T: Index {
66    buffer: Buffer<[T]>,
67    primitives: PrimitiveType,
68}
69
70impl<T> IndexBuffer<T> where T: Index {
71    /// Builds a new index buffer from a list of indices and a primitive type.
72    #[inline]
73    pub fn new<F: ?Sized>(facade: &F, prim: PrimitiveType, data: &[T])
74                  -> Result<IndexBuffer<T>, CreationError>
75                  where F: Facade
76    {
77        IndexBuffer::new_impl(facade, prim, data, BufferMode::Default)
78    }
79
80    /// Builds a new index buffer from a list of indices and a primitive type.
81    #[inline]
82    pub fn dynamic<F: ?Sized>(facade: &F, prim: PrimitiveType, data: &[T])
83                      -> Result<IndexBuffer<T>, CreationError>
84                      where F: Facade
85    {
86        IndexBuffer::new_impl(facade, prim, data, BufferMode::Dynamic)
87    }
88
89    /// Builds a new index buffer from a list of indices and a primitive type.
90    #[inline]
91    pub fn persistent<F: ?Sized>(facade: &F, prim: PrimitiveType, data: &[T])
92                         -> Result<IndexBuffer<T>, CreationError>
93                         where F: Facade
94    {
95        IndexBuffer::new_impl(facade, prim, data, BufferMode::Persistent)
96    }
97
98    /// Builds a new index buffer from a list of indices and a primitive type.
99    #[inline]
100    pub fn immutable<F: ?Sized>(facade: &F, prim: PrimitiveType, data: &[T])
101                        -> Result<IndexBuffer<T>, CreationError>
102                        where F: Facade
103    {
104        IndexBuffer::new_impl(facade, prim, data, BufferMode::Immutable)
105    }
106
107    #[inline]
108    fn new_impl<F: ?Sized>(facade: &F, prim: PrimitiveType, data: &[T], mode: BufferMode)
109                   -> Result<IndexBuffer<T>, CreationError>
110                   where F: Facade
111    {
112        if !prim.is_supported(facade) {
113            return Err(CreationError::PrimitiveTypeNotSupported);
114        }
115
116        if !T::is_supported(facade) {
117            return Err(CreationError::IndexTypeNotSupported);
118        }
119
120        Ok(IndexBuffer {
121            buffer: Buffer::new(facade, data, BufferType::ElementArrayBuffer, mode)?,
122            primitives: prim,
123        })
124    }
125
126    /// Builds a new empty index buffer.
127    #[inline]
128    pub fn empty<F: ?Sized>(facade: &F, prim: PrimitiveType, len: usize)
129                    -> Result<IndexBuffer<T>, CreationError>
130                    where F: Facade
131    {
132        IndexBuffer::empty_impl(facade, prim, len, BufferMode::Default)
133    }
134
135    /// Builds a new empty index buffer.
136    #[inline]
137    pub fn empty_dynamic<F: ?Sized>(facade: &F, prim: PrimitiveType, len: usize)
138                            -> Result<IndexBuffer<T>, CreationError>
139                            where F: Facade
140    {
141        IndexBuffer::empty_impl(facade, prim, len, BufferMode::Dynamic)
142    }
143
144    /// Builds a new empty index buffer.
145    #[inline]
146    pub fn empty_persistent<F: ?Sized>(facade: &F, prim: PrimitiveType, len: usize)
147                               -> Result<IndexBuffer<T>, CreationError>
148                               where F: Facade
149    {
150        IndexBuffer::empty_impl(facade, prim, len, BufferMode::Persistent)
151    }
152
153    /// Builds a new empty index buffer.
154    #[inline]
155    pub fn empty_immutable<F: ?Sized>(facade: &F, prim: PrimitiveType, len: usize)
156                              -> Result<IndexBuffer<T>, CreationError>
157                              where F: Facade
158    {
159        IndexBuffer::empty_impl(facade, prim, len, BufferMode::Immutable)
160    }
161
162    #[inline]
163    fn empty_impl<F: ?Sized>(facade: &F, prim: PrimitiveType, len: usize, mode: BufferMode)
164                     -> Result<IndexBuffer<T>, CreationError>
165                     where F: Facade
166    {
167        if !prim.is_supported(facade) {
168            return Err(CreationError::PrimitiveTypeNotSupported);
169        }
170
171        if !T::is_supported(facade) {
172            return Err(CreationError::IndexTypeNotSupported);
173        }
174
175        Ok(IndexBuffer {
176            buffer: Buffer::empty_array(facade, BufferType::ElementArrayBuffer, len,
177                                                 mode)?,
178            primitives: prim,
179        })
180    }
181
182    /// Returns the type of primitives associated with this index buffer.
183    #[inline]
184    pub fn get_primitives_type(&self) -> PrimitiveType {
185        self.primitives
186    }
187
188    /// Returns the data type of the indices inside this index buffer.
189    #[inline]
190    pub fn get_indices_type(&self) -> IndexType {
191        <T as Index>::get_type()
192    }
193
194    /// Returns `None` if out of range.
195    #[inline]
196    pub fn slice<R: RangeArgument<usize>>(&self, range: R) -> Option<IndexBufferSlice<'_, T>> {
197        self.buffer.slice(range).map(|b| {
198            IndexBufferSlice {
199                buffer: b,
200                primitives: self.primitives,
201            }
202        })
203    }
204}
205
206impl<T> Deref for IndexBuffer<T> where T: Index {
207    type Target = Buffer<[T]>;
208
209    #[inline]
210    fn deref(&self) -> &Buffer<[T]> {
211        &self.buffer
212    }
213}
214
215impl<T> DerefMut for IndexBuffer<T> where T: Index {
216    #[inline]
217    fn deref_mut(&mut self) -> &mut Buffer<[T]> {
218        &mut self.buffer
219    }
220}
221
222impl<'a, T> From<&'a IndexBuffer<T>> for BufferSlice<'a, [T]> where T: Index {
223    #[inline]
224    fn from(b: &'a IndexBuffer<T>) -> BufferSlice<'a, [T]> {
225        let b: &Buffer<[T]> = &*b;
226        b.as_slice()
227    }
228}
229
230impl<'a, T> From<&'a mut IndexBuffer<T>> for BufferMutSlice<'a, [T]> where T: Index {
231    #[inline]
232    fn from(b: &'a mut IndexBuffer<T>) -> BufferMutSlice<'a, [T]> {
233        let b: &mut Buffer<[T]> = &mut *b;
234        b.as_mut_slice()
235    }
236}
237
238// TODO: remove this
239impl<T> GlObject for IndexBuffer<T> where T: Index {
240    type Id = gl::types::GLuint;
241
242    #[inline]
243    fn get_id(&self) -> gl::types::GLuint {
244        self.buffer.get_id()
245    }
246}
247
248impl<'a, T> From<&'a IndexBuffer<T>> for IndicesSource<'a> where T: Index {
249    #[inline]
250    fn from(buf: &'a IndexBuffer<T>) -> IndicesSource<'a> {
251        IndicesSource::IndexBuffer {
252            buffer: buf.buffer.as_slice_any(),
253            data_type: buf.get_indices_type(),
254            primitives: buf.primitives,
255        }
256    }
257}
258
259/// Slice of an `IndexBuffer`.
260#[derive(Debug)]
261pub struct IndexBufferSlice<'a, T> where T: Index {
262    buffer: BufferSlice<'a, [T]>,
263    primitives: PrimitiveType,
264}
265
266impl<'a, T: 'a> IndexBufferSlice<'a, T> where T: Index {
267    /// Returns the type of primitives associated with this index buffer.
268    #[inline]
269    pub fn get_primitives_type(&self) -> PrimitiveType {
270        self.primitives
271    }
272
273    /// Returns the data type of the indices inside this index buffer.
274    #[inline]
275    pub fn get_indices_type(&self) -> IndexType {
276        <T as Index>::get_type()
277    }
278
279    /// Returns `None` if out of range.
280    #[inline]
281    pub fn slice<R: RangeArgument<usize>>(&self, range: R) -> Option<IndexBufferSlice<'a, T>> {
282        self.buffer.slice(range).map(|b| {
283            IndexBufferSlice {
284                buffer: b,
285                primitives: self.primitives,
286            }
287        })
288    }
289}
290
291impl<'a, T> Deref for IndexBufferSlice<'a, T> where T: Index {
292    type Target = BufferSlice<'a, [T]>;
293
294    #[inline]
295    fn deref(&self) -> &BufferSlice<'a, [T]> {
296        &self.buffer
297    }
298}
299
300impl<'a, T> DerefMut for IndexBufferSlice<'a, T> where T: Index {
301    #[inline]
302    fn deref_mut(&mut self) -> &mut BufferSlice<'a, [T]> {
303        &mut self.buffer
304    }
305}
306
307impl<'a, T> From<IndexBufferSlice<'a, T>> for BufferSlice<'a, [T]> where T: Index {
308    #[inline]
309    fn from(b: IndexBufferSlice<'a, T>) -> BufferSlice<'a, [T]> {
310        b.buffer
311    }
312}
313
314impl<'a, T> From<IndexBufferSlice<'a, T>> for IndicesSource<'a> where T: Index {
315    #[inline]
316    fn from(buf: IndexBufferSlice<'a, T>) -> IndicesSource<'a> {
317        IndicesSource::IndexBuffer {
318            buffer: buf.buffer.as_slice_any(),
319            data_type: buf.get_indices_type(),
320            primitives: buf.primitives,
321        }
322    }
323}
324
325impl<'a, 'r, T> From<&'r IndexBufferSlice<'a, T>> for IndicesSource<'a> where T: Index {
326    #[inline]
327    fn from(buf: &'r IndexBufferSlice<'a, T>) -> IndicesSource<'a> {
328        IndicesSource::IndexBuffer {
329            buffer: buf.buffer.as_slice_any(),
330            data_type: buf.get_indices_type(),
331            primitives: buf.primitives,
332        }
333    }
334}
335
336/// An `IndexBuffer` without any type information.
337///
338/// Makes it easier to store in a `Vec` or return from a function, for example.
339#[derive(Debug)]
340pub struct IndexBufferAny {
341    buffer: BufferAny,
342    primitives: PrimitiveType,
343    data_type: IndexType,
344}
345
346impl IndexBufferAny {
347    /// Returns the type of primitives associated with this index buffer.
348    #[inline]
349    pub fn get_primitives_type(&self) -> PrimitiveType {
350        self.primitives
351    }
352
353    /// Returns the data type of the indices inside this index buffer.
354    #[inline]
355    pub fn get_indices_type(&self) -> IndexType {
356        self.data_type
357    }
358}
359
360impl Deref for IndexBufferAny {
361    type Target = BufferAny;
362
363    #[inline]
364    fn deref(&self) -> &BufferAny {
365        &self.buffer
366    }
367}
368
369impl DerefMut for IndexBufferAny {
370    #[inline]
371    fn deref_mut(&mut self) -> &mut BufferAny {
372        &mut self.buffer
373    }
374}
375
376impl<T> From<IndexBuffer<T>> for IndexBufferAny where T: Index {
377    #[inline]
378    fn from(buffer: IndexBuffer<T>) -> IndexBufferAny {
379        let ty = buffer.get_indices_type();
380
381        IndexBufferAny {
382            buffer: buffer.buffer.into(),
383            data_type: ty,
384            primitives: buffer.primitives,
385        }
386    }
387}
388
389impl<'a> From<&'a IndexBufferAny> for IndicesSource<'a> {
390    #[inline]
391    fn from(buf: &'a IndexBufferAny) -> IndicesSource<'a> {
392        IndicesSource::IndexBuffer {
393            buffer: buf.buffer.as_slice_any(),
394            data_type: buf.data_type,
395            primitives: buf.primitives,
396        }
397    }
398}