glium/uniforms/
buffer.rs

1use crate::buffer::{Content, Buffer, BufferAny, BufferType, BufferMode, BufferCreationError};
2use crate::buffer::{BufferSlice, BufferMutSlice};
3use crate::uniforms::{AsUniformValue, UniformBlock, UniformValue, LayoutMismatchError};
4use crate::program;
5
6use crate::gl;
7use crate::GlObject;
8
9use std::ops::{Deref, DerefMut};
10
11use crate::backend::Facade;
12
13/// Buffer that contains a uniform block.
14///
15/// For example, to use a `UniformBuffer<[u32; 8]>`, you must declare it in GLSL as
16///```ignore
17///     uniform MyBlock {
18///         uint array[8];
19///     };
20///```
21///
22/// and pass it to `uniform!` like this:
23///     # use glium::uniform;
24///     uniform! {
25///         MyBlock: &buffer,
26///     }
27#[derive(Debug)]
28pub struct UniformBuffer<T: ?Sized> where T: Content {
29    buffer: Buffer<T>,
30}
31
32/// Same as `UniformBuffer` but doesn't contain any information about the type.
33#[derive(Debug)]
34pub struct TypelessUniformBuffer {
35    buffer: BufferAny,
36}
37
38impl<T: ?Sized + Content> GlObject for UniformBuffer<T> {
39    type Id = gl::types::GLuint;
40
41    #[inline]
42    fn get_id(&self) -> gl::types::GLuint {
43        self.buffer.get_id()
44    }
45}
46
47impl<T> UniformBuffer<T> where T: Copy {
48    /// Uploads data in the uniforms buffer.
49    #[inline]
50    pub fn new<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
51                  where F: Facade
52    {
53        UniformBuffer::new_impl(facade, data, BufferMode::Default)
54    }
55
56    /// Uploads data in the uniforms buffer.
57    #[inline]
58    pub fn dynamic<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
59                      where F: Facade
60    {
61        UniformBuffer::new_impl(facade, data, BufferMode::Dynamic)
62    }
63
64    /// Uploads data in the uniforms buffer.
65    #[inline]
66    pub fn persistent<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
67                  where F: Facade
68    {
69        UniformBuffer::new_impl(facade, data, BufferMode::Persistent)
70    }
71
72    /// Uploads data in the uniforms buffer.
73    #[inline]
74    pub fn immutable<F: ?Sized>(facade: &F, data: T) -> Result<UniformBuffer<T>, BufferCreationError>
75                        where F: Facade
76    {
77        UniformBuffer::new_impl(facade, data, BufferMode::Immutable)
78    }
79
80    #[inline]
81    fn new_impl<F: ?Sized>(facade: &F, data: T, mode: BufferMode)
82                   -> Result<UniformBuffer<T>, BufferCreationError>
83                   where F: Facade
84    {
85        let buffer = Buffer::new(facade, &data, BufferType::UniformBuffer, mode)?;
86
87        Ok(UniformBuffer {
88            buffer,
89        })
90    }
91
92    /// Creates an empty buffer.
93    #[inline]
94    pub fn empty<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError> where F: Facade {
95        UniformBuffer::empty_impl(facade, BufferMode::Default)
96    }
97
98    /// Creates an empty buffer.
99    #[inline]
100    pub fn empty_dynamic<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
101                            where F: Facade
102    {
103        UniformBuffer::empty_impl(facade, BufferMode::Dynamic)
104    }
105
106    /// Creates an empty buffer.
107    #[inline]
108    pub fn empty_persistent<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
109                               where F: Facade
110    {
111        UniformBuffer::empty_impl(facade, BufferMode::Persistent)
112    }
113
114    /// Creates an empty buffer.
115    #[inline]
116    pub fn empty_immutable<F: ?Sized>(facade: &F) -> Result<UniformBuffer<T>, BufferCreationError>
117                              where F: Facade
118    {
119        UniformBuffer::empty_impl(facade, BufferMode::Immutable)
120    }
121
122    #[inline]
123    fn empty_impl<F: ?Sized>(facade: &F, mode: BufferMode) -> Result<UniformBuffer<T>, BufferCreationError>
124                     where F: Facade
125    {
126        let buffer = Buffer::empty(facade, BufferType::UniformBuffer, mode)?;
127
128        Ok(UniformBuffer {
129            buffer,
130        })
131    }
132}
133
134impl<T: ?Sized> UniformBuffer<T> where T: Content {
135    /// Creates an empty buffer.
136    ///
137    /// # Panic
138    ///
139    /// Panics if the size passed as parameter is not suitable for the type of data.
140    ///
141    #[inline]
142    pub fn empty_unsized<F: ?Sized>(facade: &F, size: usize)
143                            -> Result<UniformBuffer<T>, BufferCreationError>
144                            where F: Facade
145    {
146        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Default)
147    }
148
149    /// Creates an empty buffer.
150    ///
151    /// # Panic
152    ///
153    /// Panics if the size passed as parameter is not suitable for the type of data.
154    ///
155    #[inline]
156    pub fn empty_unsized_dynamic<F: ?Sized>(facade: &F, size: usize)
157                                    -> Result<UniformBuffer<T>, BufferCreationError>
158                                    where F: Facade
159    {
160        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Dynamic)
161    }
162
163    /// Creates an empty buffer.
164    ///
165    /// # Panic
166    ///
167    /// Panics if the size passed as parameter is not suitable for the type of data.
168    ///
169    #[inline]
170    pub fn empty_unsized_persistent<F: ?Sized>(facade: &F, size: usize)
171                                       -> Result<UniformBuffer<T>, BufferCreationError>
172                                       where F: Facade
173    {
174        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Persistent)
175    }
176
177    /// Creates an empty buffer.
178    ///
179    /// # Panic
180    ///
181    /// Panics if the size passed as parameter is not suitable for the type of data.
182    ///
183    #[inline]
184    pub fn empty_unsized_immutable<F: ?Sized>(facade: &F, size: usize)
185                                      -> Result<UniformBuffer<T>, BufferCreationError>
186                                      where F: Facade
187    {
188        UniformBuffer::empty_unsized_impl(facade, size, BufferMode::Immutable)
189    }
190
191    #[inline]
192    fn empty_unsized_impl<F: ?Sized>(facade: &F, size: usize, mode: BufferMode)
193                             -> Result<UniformBuffer<T>, BufferCreationError>
194                             where F: Facade
195    {
196        let buffer = Buffer::empty_unsized(facade, BufferType::UniformBuffer, size, mode)?;
197
198        Ok(UniformBuffer {
199            buffer,
200        })
201    }
202}
203
204impl<T: ?Sized> Deref for UniformBuffer<T> where T: Content {
205    type Target = Buffer<T>;
206
207    #[inline]
208    fn deref(&self) -> &Buffer<T> {
209        &self.buffer
210    }
211}
212
213impl<T: ?Sized> DerefMut for UniformBuffer<T> where T: Content {
214    #[inline]
215    fn deref_mut(&mut self) -> &mut Buffer<T> {
216        &mut self.buffer
217    }
218}
219
220impl<'a, T: ?Sized> From<&'a UniformBuffer<T>> for BufferSlice<'a, T> where T: Content {
221    #[inline]
222    fn from(b: &'a UniformBuffer<T>) -> BufferSlice<'a, T> {
223        b.buffer.as_slice()
224    }
225}
226
227impl<'a, T: ?Sized> From<&'a mut UniformBuffer<T>> for BufferMutSlice<'a, T> where T: Content {
228    #[inline]
229    fn from(b: &'a mut UniformBuffer<T>) -> BufferMutSlice<'a, T> {
230        b.buffer.as_mut_slice()
231    }
232}
233
234impl<'a, T: ?Sized> AsUniformValue for &'a UniformBuffer<T> where T: UniformBlock + Content {
235    #[inline]
236    fn as_uniform_value(&self) -> UniformValue<'_> {
237        #[inline]
238        fn f<T: ?Sized>(block: &program::UniformBlock)
239                        -> Result<(), LayoutMismatchError> where T: UniformBlock + Content
240        {
241            // TODO: more checks?
242            T::matches(&block.layout, 0)
243        }
244
245        UniformValue::Block(self.buffer.as_slice_any(), f::<T>)
246    }
247}