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
12pub struct SamplerObject {
14 id: gl::types::GLuint,
15 destroyed: bool,
16}
17
18impl SamplerObject {
19 pub fn new(ctxt: &mut CommandContext<'_>, behavior: &SamplerBehavior) -> SamplerObject {
21 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 #[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
95pub fn get_sampler(ctxt: &mut CommandContext<'_>, behavior: &SamplerBehavior)
98 -> Result<gl::types::GLuint, DrawError>
99{
100 if ctxt.version < &Version(Api::Gl, 3, 2) && !ctxt.extensions.gl_arb_sampler_objects {
102 return Err(DrawError::SamplersNotSupported);
103 }
104
105 if let Some(obj) = ctxt.samplers.get(behavior) {
107 return Ok(obj.get_id());
108 }
109
110 let sampler = SamplerObject::new(ctxt, behavior);
112 let id = sampler.get_id();
113 ctxt.samplers.insert(*behavior, sampler);
114 Ok(id)
115}