glium/
sampler_object.rs

1use crate::DrawError;
2
3use crate::uniforms::SamplerBehavior;
4
5use crate::gl;
6use crate::context::CommandContext;
7use crate::version::Version;
8use crate::version::Api;
9use crate::GlObject;
10use crate::ToGlEnum;
11
12/// An OpenGL sampler object.
13pub struct SamplerObject {
14    id: gl::types::GLuint,
15    destroyed: bool,
16}
17
18impl SamplerObject {
19    /// Builds a new sampler object.
20    pub fn new(ctxt: &mut CommandContext<'_>, behavior: &SamplerBehavior) -> SamplerObject {
21        // making sure that the backend supports samplers
22        assert!(ctxt.version >= &Version(Api::Gl, 3, 2) ||
23                ctxt.version >= &Version(Api::GlEs, 3, 0) ||
24                ctxt.extensions.gl_arb_sampler_objects);
25
26        let sampler = unsafe {
27            let mut sampler: gl::types::GLuint = 0;
28            ctxt.gl.GenSamplers(1, &mut sampler);
29            sampler
30        };
31
32        unsafe {
33            ctxt.gl.SamplerParameteri(sampler, gl::TEXTURE_WRAP_S,
34                                      behavior.wrap_function.0.to_glenum() as gl::types::GLint);
35            ctxt.gl.SamplerParameteri(sampler, gl::TEXTURE_WRAP_T,
36                                      behavior.wrap_function.1.to_glenum() as gl::types::GLint);
37            ctxt.gl.SamplerParameteri(sampler, gl::TEXTURE_WRAP_R,
38                                      behavior.wrap_function.2.to_glenum() as gl::types::GLint);
39            ctxt.gl.SamplerParameteri(sampler, gl::TEXTURE_MIN_FILTER,
40                                      behavior.minify_filter.to_glenum() as gl::types::GLint);
41            ctxt.gl.SamplerParameteri(sampler, gl::TEXTURE_MAG_FILTER,
42                                      behavior.magnify_filter.to_glenum() as gl::types::GLint);
43
44            if let Some(dtc) = behavior.depth_texture_comparison {
45                ctxt.gl.SamplerParameteri(sampler, gl::TEXTURE_COMPARE_MODE,
46                                          gl::COMPARE_R_TO_TEXTURE as gl::types::GLint);
47                ctxt.gl.SamplerParameteri(sampler, gl::TEXTURE_COMPARE_FUNC,
48                                          dtc.to_glenum() as gl::types::GLint);
49            }
50
51            if let Some(max_value) = ctxt.capabilities.max_texture_max_anisotropy {
52                let value = if behavior.max_anisotropy as f32 > max_value {
53                    max_value
54                } else {
55                    behavior.max_anisotropy as f32
56                };
57
58                ctxt.gl.SamplerParameterf(sampler, gl::TEXTURE_MAX_ANISOTROPY_EXT, value);
59            }
60        }
61
62        SamplerObject {
63            id: sampler,
64            destroyed: false,
65        }
66    }
67
68    ///
69    #[inline]
70    pub fn destroy(mut self, ctxt: &mut CommandContext<'_>) {
71        self.destroyed = true;
72
73        unsafe {
74            ctxt.gl.DeleteSamplers(1, [self.id].as_ptr());
75        }
76    }
77}
78
79impl GlObject for SamplerObject {
80    type Id = gl::types::GLuint;
81
82    #[inline]
83    fn get_id(&self) -> gl::types::GLuint {
84        self.id
85    }
86}
87
88impl Drop for SamplerObject {
89    #[inline]
90    fn drop(&mut self) {
91        assert!(self.destroyed);
92    }
93}
94
95/// Returns the sampler corresponding to the given behavior, or a draw error if
96/// samplers are not supported.
97pub fn get_sampler(ctxt: &mut CommandContext<'_>, behavior: &SamplerBehavior)
98                   -> Result<gl::types::GLuint, DrawError>
99{
100    // checking for compatibility
101    if ctxt.version < &Version(Api::Gl, 3, 2) && !ctxt.extensions.gl_arb_sampler_objects {
102        return Err(DrawError::SamplersNotSupported);
103    }
104
105    // looking for an existing sampler
106    if let Some(obj) = ctxt.samplers.get(behavior) {
107        return Ok(obj.get_id());
108    }
109
110    // builds a new sampler
111    let sampler = SamplerObject::new(ctxt, behavior);
112    let id = sampler.get_id();
113    ctxt.samplers.insert(*behavior, sampler);
114    Ok(id)
115}