| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ |
| |
| use std::cell::Cell; |
| |
| use canvas_traits::webgl::WebGLError::*; |
| use canvas_traits::webgl::{WebGLCommand, WebGLSamplerId, webgl_channel}; |
| use dom_struct::dom_struct; |
| |
| use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants; |
| use crate::dom::bindings::inheritance::Castable; |
| use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object}; |
| use crate::dom::bindings::root::DomRoot; |
| use crate::dom::webgl::webglobject::WebGLObject; |
| use crate::dom::webgl::webglrenderingcontext::{Operation, WebGLRenderingContext}; |
| use crate::script_runtime::CanGc; |
| |
| #[dom_struct] |
| pub(crate) struct WebGLSampler { |
| webgl_object: WebGLObject, |
| #[no_trace] |
| gl_id: WebGLSamplerId, |
| marked_for_deletion: Cell<bool>, |
| } |
| |
| #[derive(Clone, Copy)] |
| pub(crate) enum WebGLSamplerValue { |
| Float(f32), |
| GLenum(u32), |
| } |
| |
| fn validate_params(pname: u32, value: WebGLSamplerValue) -> bool { |
| match value { |
| WebGLSamplerValue::GLenum(value) => { |
| let allowed_values = match pname { |
| constants::TEXTURE_MIN_FILTER => &[ |
| constants::NEAREST, |
| constants::LINEAR, |
| constants::NEAREST_MIPMAP_NEAREST, |
| constants::LINEAR_MIPMAP_NEAREST, |
| constants::NEAREST_MIPMAP_LINEAR, |
| constants::LINEAR_MIPMAP_LINEAR, |
| ][..], |
| constants::TEXTURE_MAG_FILTER => &[constants::NEAREST, constants::LINEAR][..], |
| constants::TEXTURE_WRAP_R | |
| constants::TEXTURE_WRAP_S | |
| constants::TEXTURE_WRAP_T => &[ |
| constants::CLAMP_TO_EDGE, |
| constants::MIRRORED_REPEAT, |
| constants::REPEAT, |
| ][..], |
| constants::TEXTURE_COMPARE_MODE => { |
| &[constants::NONE, constants::COMPARE_REF_TO_TEXTURE][..] |
| }, |
| constants::TEXTURE_COMPARE_FUNC => &[ |
| constants::LEQUAL, |
| constants::GEQUAL, |
| constants::LESS, |
| constants::GREATER, |
| constants::EQUAL, |
| constants::NOTEQUAL, |
| constants::ALWAYS, |
| constants::NEVER, |
| ][..], |
| _ => &[][..], |
| }; |
| allowed_values.contains(&value) |
| }, |
| WebGLSamplerValue::Float(_) => matches!( |
| pname, |
| constants::TEXTURE_MIN_LOD | constants::TEXTURE_MAX_LOD |
| ), |
| } |
| } |
| |
| impl WebGLSampler { |
| fn new_inherited(context: &WebGLRenderingContext, id: WebGLSamplerId) -> Self { |
| Self { |
| webgl_object: WebGLObject::new_inherited(context), |
| gl_id: id, |
| marked_for_deletion: Cell::new(false), |
| } |
| } |
| |
| pub(crate) fn new(context: &WebGLRenderingContext, can_gc: CanGc) -> DomRoot<Self> { |
| let (sender, receiver) = webgl_channel().unwrap(); |
| context.send_command(WebGLCommand::GenerateSampler(sender)); |
| let id = receiver.recv().unwrap(); |
| |
| reflect_dom_object( |
| Box::new(Self::new_inherited(context, id)), |
| &*context.global(), |
| can_gc, |
| ) |
| } |
| |
| pub(crate) fn delete(&self, operation_fallibility: Operation) { |
| if !self.marked_for_deletion.get() { |
| self.marked_for_deletion.set(true); |
| |
| let command = WebGLCommand::DeleteSampler(self.gl_id); |
| let context = self.upcast::<WebGLObject>().context(); |
| match operation_fallibility { |
| Operation::Fallible => context.send_command_ignored(command), |
| Operation::Infallible => context.send_command(command), |
| } |
| } |
| } |
| |
| pub(crate) fn is_valid(&self) -> bool { |
| !self.marked_for_deletion.get() |
| } |
| |
| pub(crate) fn bind( |
| &self, |
| context: &WebGLRenderingContext, |
| unit: u32, |
| ) -> Result<(), canvas_traits::webgl::WebGLError> { |
| if !self.is_valid() { |
| return Err(InvalidOperation); |
| } |
| context.send_command(WebGLCommand::BindSampler(unit, self.gl_id)); |
| Ok(()) |
| } |
| |
| pub(crate) fn set_parameter( |
| &self, |
| context: &WebGLRenderingContext, |
| pname: u32, |
| value: WebGLSamplerValue, |
| ) -> Result<(), canvas_traits::webgl::WebGLError> { |
| if !self.is_valid() { |
| return Err(InvalidOperation); |
| } |
| if !validate_params(pname, value) { |
| return Err(InvalidEnum); |
| } |
| let command = match value { |
| WebGLSamplerValue::GLenum(value) => { |
| WebGLCommand::SetSamplerParameterInt(self.gl_id, pname, value as i32) |
| }, |
| WebGLSamplerValue::Float(value) => { |
| WebGLCommand::SetSamplerParameterFloat(self.gl_id, pname, value) |
| }, |
| }; |
| context.send_command(command); |
| Ok(()) |
| } |
| |
| pub(crate) fn get_parameter( |
| &self, |
| context: &WebGLRenderingContext, |
| pname: u32, |
| ) -> Result<WebGLSamplerValue, canvas_traits::webgl::WebGLError> { |
| if !self.is_valid() { |
| return Err(InvalidOperation); |
| } |
| match pname { |
| constants::TEXTURE_MIN_FILTER | |
| constants::TEXTURE_MAG_FILTER | |
| constants::TEXTURE_WRAP_R | |
| constants::TEXTURE_WRAP_S | |
| constants::TEXTURE_WRAP_T | |
| constants::TEXTURE_COMPARE_FUNC | |
| constants::TEXTURE_COMPARE_MODE => { |
| let (sender, receiver) = webgl_channel().unwrap(); |
| context.send_command(WebGLCommand::GetSamplerParameterInt( |
| self.gl_id, pname, sender, |
| )); |
| Ok(WebGLSamplerValue::GLenum(receiver.recv().unwrap() as u32)) |
| }, |
| constants::TEXTURE_MIN_LOD | constants::TEXTURE_MAX_LOD => { |
| let (sender, receiver) = webgl_channel().unwrap(); |
| context.send_command(WebGLCommand::GetSamplerParameterFloat( |
| self.gl_id, pname, sender, |
| )); |
| Ok(WebGLSamplerValue::Float(receiver.recv().unwrap())) |
| }, |
| _ => Err(InvalidEnum), |
| } |
| } |
| } |
| |
| impl Drop for WebGLSampler { |
| fn drop(&mut self) { |
| self.delete(Operation::Fallible); |
| } |
| } |