glium/vertex/
buffer.rs

1use std::error::Error;
2use std::fmt;
3use std::ops::{Deref, DerefMut};
4use crate::utils::range::RangeArgument;
5
6use crate::buffer::{Buffer, BufferSlice, BufferMutSlice, BufferAny, BufferType, BufferMode, BufferCreationError, Content};
7use crate::vertex::{Vertex, VerticesSource, PerInstance};
8use crate::vertex::format::VertexFormat;
9
10use crate::gl;
11use crate::GlObject;
12
13use crate::backend::Facade;
14use crate::version::{Api, Version};
15use crate::CapabilitiesSource;
16
17/// Error that can happen when creating a vertex buffer.
18#[derive(Copy, Clone, Debug)]
19pub enum CreationError {
20    /// The vertex format is not supported by the backend.
21    ///
22    /// Anything 64bits-related may not be supported.
23    FormatNotSupported,
24
25    /// Error while creating the vertex buffer.
26    BufferCreationError(BufferCreationError),
27}
28
29impl From<BufferCreationError> for CreationError {
30    #[inline]
31    fn from(err: BufferCreationError) -> CreationError {
32        CreationError::BufferCreationError(err)
33    }
34}
35
36impl fmt::Display for CreationError {
37    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
38        use self::CreationError::*;
39        let desc = match self {
40            FormatNotSupported => "The vertex format is not supported by the backend",
41            BufferCreationError(_) => "Error while creating the vertex buffer",
42        };
43        fmt.write_str(desc)
44    }
45}
46
47impl Error for CreationError {
48    fn source(&self) -> Option<&(dyn Error + 'static)> {
49        use self::CreationError::*;
50        match *self {
51            BufferCreationError(ref error) => Some(error),
52            FormatNotSupported => None,
53        }
54    }
55}
56
57impl<T: Copy> GlObject for VertexBuffer<T> {
58    type Id = gl::types::GLuint;
59
60    #[inline]
61    fn get_id(&self) -> gl::types::GLuint {
62        self.buffer.get_id()
63    }
64}
65
66/// A list of vertices loaded in the graphics card's memory.
67#[derive(Debug)]
68pub struct VertexBuffer<T> where T: Copy {
69    buffer: Buffer<[T]>,
70    bindings: VertexFormat,
71}
72
73/// Represents a slice of a `VertexBuffer`.
74pub struct VertexBufferSlice<'b, T> where T: Copy {
75    buffer: BufferSlice<'b, [T]>,
76    bindings: VertexFormat,
77}
78
79impl<'b, T: 'b> VertexBufferSlice<'b, T> where T: Copy + Content {
80    /// Creates a marker that instructs glium to use multiple instances.
81    ///
82    /// Instead of calling `surface.draw(&vertex_buffer.slice(...).unwrap(), ...)`
83    /// you can call `surface.draw(vertex_buffer.slice(...).unwrap().per_instance(), ...)`.
84    /// This will draw one instance of the geometry for each element in this buffer slice.
85    /// The attributes are still passed to the vertex shader, but each entry is passed
86    /// for each different instance.
87    #[inline]
88    pub fn per_instance(&'b self) -> Result<PerInstance<'b>, InstancingNotSupported> {
89        // TODO: don't check this here
90        if !(self.get_context().get_version() >= &Version(Api::Gl, 3, 3)) &&
91            !(self.get_context().get_version() >= &Version(Api::GlEs, 3, 0)) &&
92            !self.get_context().get_extensions().gl_arb_instanced_arrays
93        {
94            return Err(InstancingNotSupported);
95        }
96
97        Ok(PerInstance(self.buffer.as_slice_any(), self.bindings))
98    }
99}
100
101impl<T> VertexBuffer<T> where T: Vertex {
102    /// Builds a new vertex buffer.
103    ///
104    /// Note that operations such as `write` will be very slow. If you want to modify the buffer
105    /// from time to time, you should use the `dynamic` function instead.
106    ///
107    /// # Example
108    ///
109    /// ```no_run
110    /// # #[macro_use]
111    /// # extern crate glium;
112    /// # fn main() {
113    /// #[derive(Copy, Clone)]
114    /// struct Vertex {
115    ///     position: [f32; 3],
116    ///     texcoords: [f32; 2],
117    /// }
118    ///
119    /// implement_vertex!(Vertex, position, texcoords);
120    /// # use glutin::surface::{ResizeableSurface, SurfaceTypeTrait};
121    /// # fn example<T>(display: glium::Display<T>) where T: SurfaceTypeTrait + ResizeableSurface {
122    /// let vertex_buffer = glium::VertexBuffer::new(&display, &[
123    ///     Vertex { position: [0.0,  0.0, 0.0], texcoords: [0.0, 1.0] },
124    ///     Vertex { position: [5.0, -3.0, 2.0], texcoords: [1.0, 0.0] },
125    /// ]);
126    /// # }
127    /// # }
128    /// ```
129    ///
130    #[inline]
131    pub fn new<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
132                  where F: Facade
133    {
134        VertexBuffer::new_impl(facade, data, BufferMode::Default)
135    }
136
137    /// Builds a new vertex buffer.
138    ///
139    /// This function will create a buffer that is intended to be modified frequently.
140    #[inline]
141    pub fn dynamic<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
142                      where F: Facade
143    {
144        VertexBuffer::new_impl(facade, data, BufferMode::Dynamic)
145    }
146
147    /// Builds a new vertex buffer.
148    #[inline]
149    pub fn persistent<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
150                         where F: Facade
151    {
152        VertexBuffer::new_impl(facade, data, BufferMode::Persistent)
153    }
154
155    /// Builds a new vertex buffer.
156    #[inline]
157    pub fn immutable<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
158                        where F: Facade
159    {
160        VertexBuffer::new_impl(facade, data, BufferMode::Immutable)
161    }
162
163    #[inline]
164    fn new_impl<F: ?Sized>(facade: &F, data: &[T], mode: BufferMode)
165                   -> Result<VertexBuffer<T>, CreationError>
166                   where F: Facade
167    {
168        if !T::is_supported(facade) {
169            return Err(CreationError::FormatNotSupported);
170        }
171
172        let buffer = Buffer::new(facade, data, BufferType::ArrayBuffer, mode)?;
173        Ok(buffer.into())
174    }
175
176    /// Builds an empty vertex buffer.
177    ///
178    /// The parameter indicates the number of elements.
179    #[inline]
180    pub fn empty<F: ?Sized>(facade: &F, elements: usize) -> Result<VertexBuffer<T>, CreationError>
181                    where F: Facade
182    {
183        VertexBuffer::empty_impl(facade, elements, BufferMode::Default)
184    }
185
186    /// Builds an empty vertex buffer.
187    ///
188    /// The parameter indicates the number of elements.
189    #[inline]
190    pub fn empty_dynamic<F: ?Sized>(facade: &F, elements: usize) -> Result<VertexBuffer<T>, CreationError>
191                            where F: Facade
192    {
193        VertexBuffer::empty_impl(facade, elements, BufferMode::Dynamic)
194    }
195
196    /// Builds an empty vertex buffer.
197    ///
198    /// The parameter indicates the number of elements.
199    #[inline]
200    pub fn empty_persistent<F: ?Sized>(facade: &F, elements: usize)
201                               -> Result<VertexBuffer<T>, CreationError>
202                               where F: Facade
203    {
204        VertexBuffer::empty_impl(facade, elements, BufferMode::Persistent)
205    }
206
207    /// Builds an empty vertex buffer.
208    ///
209    /// The parameter indicates the number of elements.
210    #[inline]
211    pub fn empty_immutable<F: ?Sized>(facade: &F, elements: usize) -> Result<VertexBuffer<T>, CreationError>
212                              where F: Facade
213    {
214        VertexBuffer::empty_impl(facade, elements, BufferMode::Immutable)
215    }
216
217    #[inline]
218    fn empty_impl<F: ?Sized>(facade: &F, elements: usize, mode: BufferMode)
219                     -> Result<VertexBuffer<T>, CreationError>
220                     where F: Facade
221    {
222        if !T::is_supported(facade) {
223            return Err(CreationError::FormatNotSupported);
224        }
225
226        let buffer = Buffer::empty_array(facade, BufferType::ArrayBuffer, elements, mode)?;
227        Ok(buffer.into())
228    }
229}
230
231impl<T> VertexBuffer<T> where T: Copy {
232    /// Builds a new vertex buffer from an indeterminate data type and bindings.
233    ///
234    /// # Example
235    ///
236    /// ```no_run
237    /// # use glutin::surface::{ResizeableSurface, SurfaceTypeTrait};
238    /// # fn example<T>(display: glium::Display<T>) where T: SurfaceTypeTrait + ResizeableSurface {
239    /// use std::borrow::Cow;
240    ///
241    /// const BINDINGS: glium::vertex::VertexFormat = &[(
242    ///         Cow::Borrowed("position"), 0, -1,
243    ///         glium::vertex::AttributeType::F32F32,
244    ///         false,
245    ///     ), (
246    ///         Cow::Borrowed("color"), 2 * ::std::mem::size_of::<f32>(), -1,
247    ///         glium::vertex::AttributeType::F32,
248    ///         false,
249    ///     ),
250    /// ];
251    ///
252    /// let data = vec![
253    ///     1.0, -0.3, 409.0,
254    ///     -0.4, 2.8, 715.0f32
255    /// ];
256    ///
257    /// let vertex_buffer = unsafe {
258    ///     glium::VertexBuffer::new_raw(&display, &data, BINDINGS, 3 * ::std::mem::size_of::<f32>())
259    /// };
260    /// # }
261    /// ```
262    ///
263    #[inline]
264    pub unsafe fn new_raw<F: ?Sized>(facade: &F, data: &[T],
265                             bindings: VertexFormat, elements_size: usize)
266                             -> Result<VertexBuffer<T>, CreationError>
267                             where F: Facade
268    {
269        // FIXME: check that the format is supported
270
271        Ok(VertexBuffer {
272            buffer: Buffer::new(facade, data, BufferType::ArrayBuffer,
273                                         BufferMode::Default)?,
274            bindings,
275        })
276    }
277
278    /// Dynamic version of `new_raw`.
279    #[inline]
280    pub unsafe fn new_raw_dynamic<F: ?Sized>(facade: &F, data: &[T],
281                                     bindings: VertexFormat, elements_size: usize)
282                                     -> Result<VertexBuffer<T>, CreationError>
283                                     where F: Facade
284    {
285        // FIXME: check that the format is supported
286
287        Ok(VertexBuffer {
288            buffer: Buffer::new(facade, data, BufferType::ArrayBuffer,
289                                         BufferMode::Dynamic)?,
290            bindings,
291        })
292    }
293
294    /// Accesses a slice of the buffer.
295    ///
296    /// Returns `None` if the slice is out of range.
297    #[inline]
298    pub fn slice<R: RangeArgument<usize>>(&self, range: R) -> Option<VertexBufferSlice<'_, T>> {
299        let slice = match self.buffer.slice(range) {
300            None => return None,
301            Some(s) => s
302        };
303
304        Some(VertexBufferSlice {
305            buffer: slice,
306            bindings: self.bindings,
307        })
308    }
309
310    /// Returns the associated `VertexFormat`.
311    #[inline]
312    pub fn get_bindings(&self) -> &VertexFormat {
313        &self.bindings
314    }
315
316    /// Creates a marker that instructs glium to use multiple instances.
317    ///
318    /// Instead of calling `surface.draw(&vertex_buffer, ...)` you can call
319    /// `surface.draw(vertex_buffer.per_instance(), ...)`. This will draw one instance of the
320    /// geometry for each element in this buffer. The attributes are still passed to the
321    /// vertex shader, but each entry is passed for each different instance.
322    #[inline]
323    pub fn per_instance(&self) -> Result<PerInstance<'_>, InstancingNotSupported> {
324        // TODO: don't check this here
325        if !(self.buffer.get_context().get_version() >= &Version(Api::Gl, 3, 3)) &&
326            !(self.get_context().get_version() >= &Version(Api::GlEs, 3, 0)) &&
327            !self.buffer.get_context().get_extensions().gl_arb_instanced_arrays
328        {
329            return Err(InstancingNotSupported);
330        }
331
332        Ok(PerInstance(self.buffer.as_slice_any(), self.bindings))
333    }
334}
335
336impl<T> VertexBuffer<T> where T: Copy + Send + 'static {
337    /// Discard the type information and turn the vertex buffer into a `VertexBufferAny`.
338    #[inline]
339    #[deprecated(note = "use .into() instead.")]
340    pub fn into_vertex_buffer_any(self) -> VertexBufferAny {
341        self.into_vertex_buffer_any_inner()
342    }
343    #[inline]
344    fn into_vertex_buffer_any_inner(self) -> VertexBufferAny {
345        VertexBufferAny {
346            buffer: self.buffer.into(),
347            bindings: self.bindings,
348        }
349    }
350}
351
352impl<T> From<Buffer<[T]>> for VertexBuffer<T> where T: Vertex + Copy {
353    #[inline]
354    fn from(buffer: Buffer<[T]>) -> VertexBuffer<T> {
355        assert!(T::is_supported(buffer.get_context()));
356
357        let bindings = <T as Vertex>::build_bindings();
358
359        VertexBuffer {
360            buffer,
361            bindings,
362        }
363    }
364}
365
366impl<T> Deref for VertexBuffer<T> where T: Copy {
367    type Target = Buffer<[T]>;
368
369    #[inline]
370    fn deref(&self) -> &Buffer<[T]> {
371        &self.buffer
372    }
373}
374
375impl<T> DerefMut for VertexBuffer<T> where T: Copy {
376    #[inline]
377    fn deref_mut(&mut self) -> &mut Buffer<[T]> {
378        &mut self.buffer
379    }
380}
381
382impl<'a, T> From<&'a VertexBuffer<T>> for BufferSlice<'a, [T]> where T: Copy {
383    #[inline]
384    fn from(b: &'a VertexBuffer<T>) -> BufferSlice<'a, [T]> {
385        let b: &Buffer<[T]> = &*b;
386        b.as_slice()
387    }
388}
389
390impl<'a, T> From<&'a mut VertexBuffer<T>> for BufferMutSlice<'a, [T]> where T: Copy {
391    #[inline]
392    fn from(b: &'a mut VertexBuffer<T>) -> BufferMutSlice<'a, [T]> {
393        let b: &mut Buffer<[T]> = &mut *b;
394        b.as_mut_slice()
395    }
396}
397
398impl<'a, T> From<&'a VertexBuffer<T>> for VerticesSource<'a> where T: Copy {
399    #[inline]
400    fn from(this: &VertexBuffer<T>) -> VerticesSource<'_> {
401        VerticesSource::VertexBuffer(this.buffer.as_slice_any(), this.bindings, false)
402    }
403}
404
405impl<'a, T> Deref for VertexBufferSlice<'a, T> where T: Copy {
406    type Target = BufferSlice<'a, [T]>;
407
408    #[inline]
409    fn deref(&self) -> &BufferSlice<'a, [T]> {
410        &self.buffer
411    }
412}
413
414impl<'a, T> DerefMut for VertexBufferSlice<'a, T> where T: Copy {
415    #[inline]
416    fn deref_mut(&mut self) -> &mut BufferSlice<'a, [T]> {
417        &mut self.buffer
418    }
419}
420
421impl<'a, T> From<VertexBufferSlice<'a, T>> for BufferSlice<'a, [T]> where T: Copy {
422    #[inline]
423    fn from(b: VertexBufferSlice<'a, T>) -> BufferSlice<'a, [T]> {
424        b.buffer
425    }
426}
427
428impl<'a, T> From<VertexBufferSlice<'a, T>> for VerticesSource<'a> where T: Copy {
429    #[inline]
430    fn from(this: VertexBufferSlice<'a, T>) -> VerticesSource<'a> {
431        VerticesSource::VertexBuffer(this.buffer.as_slice_any(), this.bindings, false)
432    }
433}
434
435/// A list of vertices loaded in the graphics card's memory.
436///
437/// Contrary to `VertexBuffer`, this struct doesn't know about the type of data
438/// inside the buffer. Therefore you can't map or read it.
439///
440/// This struct is provided for convenience, so that you can have a `Vec<VertexBufferAny>`,
441/// or return a `VertexBufferAny` instead of a `VertexBuffer<MyPrivateVertexType>`.
442#[derive(Debug)]
443pub struct VertexBufferAny {
444    buffer: BufferAny,
445    bindings: VertexFormat,
446}
447
448impl VertexBufferAny {
449    /// Returns the number of bytes between two consecutive elements in the buffer.
450    #[inline]
451    pub fn get_elements_size(&self) -> usize {
452        self.buffer.get_elements_size()
453    }
454
455    /// Returns the number of elements in the buffer.
456    #[inline]
457    pub fn len(&self) -> usize {
458        self.buffer.get_elements_count()
459    }
460
461    /// Returns the associated `VertexFormat`.
462    #[inline]
463    pub fn get_bindings(&self) -> &VertexFormat {
464        &self.bindings
465    }
466
467    /// Turns the vertex buffer into a `VertexBuffer` without checking the type.
468    #[inline]
469    pub unsafe fn into_vertex_buffer<T: Copy>(self) -> VertexBuffer<T> {
470        unimplemented!();
471    }
472
473    /// Creates a marker that instructs glium to use multiple instances.
474    ///
475    /// Instead of calling `surface.draw(&vertex_buffer, ...)` you can call
476    /// `surface.draw(vertex_buffer.per_instance(), ...)`. This will draw one instance of the
477    /// geometry for each element in this buffer. The attributes are still passed to the
478    /// vertex shader, but each entry is passed for each different instance.
479    #[inline]
480    pub fn per_instance(&self) -> Result<PerInstance<'_>, InstancingNotSupported> {
481        // TODO: don't check this here
482        if !(self.buffer.get_context().get_version() >= &Version(Api::Gl, 3, 3)) &&
483            !(self.get_context().get_version() >= &Version(Api::GlEs, 3, 0)) &&
484            !self.buffer.get_context().get_extensions().gl_arb_instanced_arrays
485        {
486            return Err(InstancingNotSupported);
487        }
488
489        Ok(PerInstance(self.buffer.as_slice_any(), self.bindings))
490    }
491}
492
493impl<T> From<VertexBuffer<T>> for VertexBufferAny where T: Copy + Send + 'static {
494    #[inline]
495    fn from(buf: VertexBuffer<T>) -> VertexBufferAny {
496        buf.into_vertex_buffer_any_inner()
497    }
498}
499
500impl<T> From<Buffer<[T]>> for VertexBufferAny where T: Vertex + Copy + Send + 'static {
501    #[inline]
502    fn from(buf: Buffer<[T]>) -> VertexBufferAny {
503        let buf: VertexBuffer<T> = buf.into();
504        buf.into_vertex_buffer_any_inner()
505    }
506}
507
508impl Deref for VertexBufferAny {
509    type Target = BufferAny;
510
511    #[inline]
512    fn deref(&self) -> &BufferAny {
513        &self.buffer
514    }
515}
516
517impl DerefMut for VertexBufferAny {
518    #[inline]
519    fn deref_mut(&mut self) -> &mut BufferAny {
520        &mut self.buffer
521    }
522}
523
524impl<'a> From<&'a VertexBufferAny> for VerticesSource<'a> {
525    #[inline]
526    fn from(this :&VertexBufferAny) -> VerticesSource<'_> {
527        VerticesSource::VertexBuffer(this.buffer.as_slice_any(), this.bindings, false)
528    }
529}
530
531/// Instancing is not supported by the backend.
532#[derive(Debug, Copy, Clone)]
533pub struct InstancingNotSupported;