Skip to main content

fyrox_graphics_gl/
sampler.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::{server::GlGraphicsServer, ToGlConstant};
22use fyrox_graphics::{
23    error::FrameworkError,
24    sampler::{
25        Coordinate, GpuSamplerDescriptor, GpuSamplerTrait, MagnificationFilter, MinificationFilter,
26        WrapMode,
27    },
28};
29use glow::HasContext;
30use std::rc::Weak;
31
32impl ToGlConstant for MinificationFilter {
33    fn into_gl(self) -> u32 {
34        match self {
35            Self::Nearest => glow::NEAREST,
36            Self::NearestMipMapNearest => glow::NEAREST_MIPMAP_NEAREST,
37            Self::NearestMipMapLinear => glow::NEAREST_MIPMAP_LINEAR,
38            Self::Linear => glow::LINEAR,
39            Self::LinearMipMapNearest => glow::LINEAR_MIPMAP_NEAREST,
40            Self::LinearMipMapLinear => glow::LINEAR_MIPMAP_LINEAR,
41        }
42    }
43}
44
45impl ToGlConstant for MagnificationFilter {
46    fn into_gl(self) -> u32 {
47        match self {
48            Self::Nearest => glow::NEAREST,
49            Self::Linear => glow::LINEAR,
50        }
51    }
52}
53
54impl ToGlConstant for WrapMode {
55    fn into_gl(self) -> u32 {
56        match self {
57            Self::Repeat => glow::REPEAT,
58            Self::ClampToEdge => glow::CLAMP_TO_EDGE,
59            Self::ClampToBorder => glow::CLAMP_TO_BORDER,
60            Self::MirroredRepeat => glow::MIRRORED_REPEAT,
61            Self::MirrorClampToEdge => glow::MIRROR_CLAMP_TO_EDGE,
62        }
63    }
64}
65
66impl ToGlConstant for Coordinate {
67    fn into_gl(self) -> u32 {
68        match self {
69            Self::S => glow::TEXTURE_WRAP_S,
70            Self::T => glow::TEXTURE_WRAP_T,
71            Self::R => glow::TEXTURE_WRAP_R,
72        }
73    }
74}
75
76#[derive(Debug)]
77pub struct GlSampler {
78    state: Weak<GlGraphicsServer>,
79    pub(crate) id: glow::Sampler,
80}
81
82impl GpuSamplerTrait for GlSampler {}
83
84impl GlSampler {
85    pub fn new(
86        server: &GlGraphicsServer,
87        desc: GpuSamplerDescriptor,
88    ) -> Result<Self, FrameworkError> {
89        unsafe {
90            let gl = &server.gl;
91            let id = gl.create_sampler()?;
92            let GpuSamplerDescriptor {
93                min_filter,
94                mag_filter,
95                s_wrap_mode,
96                t_wrap_mode,
97                r_wrap_mode,
98                anisotropy,
99                min_lod,
100                max_lod,
101                #[allow(unused_variables)]
102                lod_bias,
103            } = desc;
104            gl.bind_sampler(0, Some(id));
105            gl.sampler_parameter_i32(id, glow::TEXTURE_MAG_FILTER, mag_filter.into_gl() as i32);
106            gl.sampler_parameter_i32(id, glow::TEXTURE_MIN_FILTER, min_filter.into_gl() as i32);
107
108            // WebGL2 does not support lod bias.
109            #[cfg(not(target_arch = "wasm32"))]
110            gl.sampler_parameter_f32(id, glow::TEXTURE_LOD_BIAS, lod_bias);
111
112            gl.sampler_parameter_f32(id, glow::TEXTURE_MIN_LOD, min_lod);
113            gl.sampler_parameter_f32(id, glow::TEXTURE_MAX_LOD, max_lod);
114            gl.sampler_parameter_f32(
115                id,
116                glow::TEXTURE_MAX_ANISOTROPY,
117                anisotropy.clamp(1.0, 16.0),
118            );
119            gl.sampler_parameter_i32(id, glow::TEXTURE_WRAP_S, s_wrap_mode.into_gl() as i32);
120            gl.sampler_parameter_i32(id, glow::TEXTURE_WRAP_T, t_wrap_mode.into_gl() as i32);
121            gl.sampler_parameter_i32(id, glow::TEXTURE_WRAP_R, r_wrap_mode.into_gl() as i32);
122            gl.bind_sampler(0, None);
123
124            Ok(Self {
125                state: server.weak(),
126                id,
127            })
128        }
129    }
130}
131
132impl Drop for GlSampler {
133    fn drop(&mut self) {
134        if let Some(state) = self.state.upgrade() {
135            unsafe {
136                state.gl.delete_sampler(self.id);
137            }
138        }
139    }
140}