mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Implement EXT_texture_filter_anisotropic
This commit is contained in:
parent
eb1dfd0775
commit
f1288cc6e0
10 changed files with 262 additions and 122 deletions
|
@ -0,0 +1,54 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use canvas_traits::webgl::WebGLVersion;
|
||||
use dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding;
|
||||
use dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding::EXTTextureFilterAnisotropicConstants;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::bindings::root::DomRoot;
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use dom_struct::dom_struct;
|
||||
use super::{WebGLExtension, WebGLExtensions, WebGLExtensionSpec};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct EXTTextureFilterAnisotropic {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl EXTTextureFilterAnisotropic {
|
||||
fn new_inherited() -> EXTTextureFilterAnisotropic {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExtension for EXTTextureFilterAnisotropic {
|
||||
type Extension = EXTTextureFilterAnisotropic;
|
||||
|
||||
fn new(ctx: &WebGLRenderingContext) -> DomRoot<Self> {
|
||||
reflect_dom_object(
|
||||
Box::new(Self::new_inherited()),
|
||||
&*ctx.global(),
|
||||
EXTTextureFilterAnisotropicBinding::Wrap,
|
||||
)
|
||||
}
|
||||
|
||||
fn spec() -> WebGLExtensionSpec {
|
||||
WebGLExtensionSpec::Specific(WebGLVersion::WebGL1)
|
||||
}
|
||||
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool {
|
||||
ext.supports_gl_extension("GL_EXT_texture_filter_anisotropic")
|
||||
}
|
||||
|
||||
fn enable(ext: &WebGLExtensions) {
|
||||
ext.enable_get_tex_parameter_name(EXTTextureFilterAnisotropicConstants::TEXTURE_MAX_ANISOTROPY_EXT);
|
||||
ext.enable_get_parameter_name(EXTTextureFilterAnisotropicConstants::MAX_TEXTURE_MAX_ANISOTROPY_EXT);
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"EXT_texture_filter_anisotropic"
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderi
|
|||
use super::{ext_constants, WebGLExtension, WebGLExtensions, WebGLExtensionSpec};
|
||||
|
||||
pub mod extshadertexturelod;
|
||||
pub mod exttexturefilteranisotropic;
|
||||
pub mod oeselementindexuint;
|
||||
pub mod oesstandardderivatives;
|
||||
pub mod oestexturefloat;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
use canvas_traits::webgl::{WebGLError, WebGLVersion};
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding::EXTTextureFilterAnisotropicConstants;
|
||||
use dom::bindings::codegen::Bindings::OESStandardDerivativesBinding::OESStandardDerivativesConstants;
|
||||
use dom::bindings::codegen::Bindings::OESTextureHalfFloatBinding::OESTextureHalfFloatConstants;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
|
@ -41,8 +42,16 @@ const DEFAULT_NOT_FILTERABLE_TEX_TYPES: [GLenum; 2] = [
|
|||
// Param names that are implemented for glGetParameter in a WebGL 1.0 context
|
||||
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||
// Example: https://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
|
||||
const DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL1: [GLenum; 1] = [
|
||||
OESStandardDerivativesConstants::FRAGMENT_SHADER_DERIVATIVE_HINT_OES
|
||||
const DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL1: [GLenum; 2] = [
|
||||
EXTTextureFilterAnisotropicConstants::MAX_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
OESStandardDerivativesConstants::FRAGMENT_SHADER_DERIVATIVE_HINT_OES,
|
||||
];
|
||||
|
||||
// Param names that are implemented for glGetTexParameter in a WebGL 1.0 context
|
||||
// but must trigger a InvalidEnum error until the related WebGL Extensions are enabled.
|
||||
// Example: https://www.khronos.org/registry/webgl/extensions/OES_standard_derivatives/
|
||||
const DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL1: [GLenum; 1] = [
|
||||
EXTTextureFilterAnisotropicConstants::TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
];
|
||||
|
||||
/// WebGL features that are enabled/disabled by WebGL Extensions.
|
||||
|
@ -57,20 +66,30 @@ struct WebGLExtensionFeatures {
|
|||
hint_targets: FnvHashSet<GLenum>,
|
||||
/// WebGL GetParameter() names enabled by extensions.
|
||||
disabled_get_parameter_names: FnvHashSet<GLenum>,
|
||||
/// WebGL GetTexParameter() names enabled by extensions.
|
||||
disabled_get_tex_parameter_names: FnvHashSet<GLenum>,
|
||||
/// WebGL OES_element_index_uint extension.
|
||||
element_index_uint_enabled: bool,
|
||||
}
|
||||
|
||||
impl WebGLExtensionFeatures {
|
||||
fn new(webgl_version: WebGLVersion) -> Self {
|
||||
let (disabled_tex_types, disabled_get_parameter_names, element_index_uint_enabled) = match webgl_version {
|
||||
let (
|
||||
disabled_tex_types,
|
||||
disabled_get_parameter_names,
|
||||
disabled_get_tex_parameter_names,
|
||||
element_index_uint_enabled,
|
||||
) = match webgl_version {
|
||||
WebGLVersion::WebGL1 => {
|
||||
(DEFAULT_DISABLED_TEX_TYPES_WEBGL1.iter().cloned().collect(),
|
||||
DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL1.iter().cloned().collect(),
|
||||
false)
|
||||
(
|
||||
DEFAULT_DISABLED_TEX_TYPES_WEBGL1.iter().cloned().collect(),
|
||||
DEFAULT_DISABLED_GET_PARAMETER_NAMES_WEBGL1.iter().cloned().collect(),
|
||||
DEFAULT_DISABLED_GET_TEX_PARAMETER_NAMES_WEBGL1.iter().cloned().collect(),
|
||||
false,
|
||||
)
|
||||
},
|
||||
WebGLVersion::WebGL2 => {
|
||||
(Default::default(), Default::default(), true)
|
||||
(Default::default(), Default::default(), Default::default(), true)
|
||||
}
|
||||
};
|
||||
Self {
|
||||
|
@ -81,6 +100,7 @@ impl WebGLExtensionFeatures {
|
|||
query_parameter_handlers: Default::default(),
|
||||
hint_targets: Default::default(),
|
||||
disabled_get_parameter_names,
|
||||
disabled_get_tex_parameter_names,
|
||||
element_index_uint_enabled,
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +256,16 @@ impl WebGLExtensions {
|
|||
!self.features.borrow().disabled_get_parameter_names.contains(&name)
|
||||
}
|
||||
|
||||
pub fn enable_get_tex_parameter_name(&self, name: GLenum) {
|
||||
self.features.borrow_mut().disabled_get_tex_parameter_names.remove(&name);
|
||||
}
|
||||
|
||||
pub fn is_get_tex_parameter_name_enabled(&self, name: GLenum) -> bool {
|
||||
!self.features.borrow().disabled_get_tex_parameter_names.contains(&name)
|
||||
}
|
||||
|
||||
fn register_all_extensions(&self) {
|
||||
self.register::<ext::exttexturefilteranisotropic::EXTTextureFilterAnisotropic>();
|
||||
self.register::<ext::oeselementindexuint::OESElementIndexUint>();
|
||||
self.register::<ext::oesstandardderivatives::OESStandardDerivatives>();
|
||||
self.register::<ext::oestexturefloat::OESTextureFloat>();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
|
||||
use canvas_traits::canvas::{byte_swap, multiply_u8_pixel};
|
||||
use canvas_traits::webgl::{DOMToTextureCommand, Parameter, ProgramParameter};
|
||||
use canvas_traits::webgl::{ShaderParameter, VertexAttrib, WebGLCommand};
|
||||
use canvas_traits::webgl::{ShaderParameter, TexParameter, VertexAttrib, WebGLCommand};
|
||||
use canvas_traits::webgl::{WebGLContextShareMode, WebGLError};
|
||||
use canvas_traits::webgl::{WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender};
|
||||
use canvas_traits::webgl::{WebGLResult, WebGLSLVersion, WebGLVersion};
|
||||
|
@ -432,27 +432,35 @@ impl WebGLRenderingContext {
|
|||
constants::TEXTURE_CUBE_MAP => self.bound_texture(target),
|
||||
_ => return self.webgl_error(InvalidEnum),
|
||||
};
|
||||
if let Some(texture) = texture {
|
||||
handle_potential_webgl_error!(self, texture.tex_parameter(target, name, value));
|
||||
|
||||
// Validate non filterable TEXTURE_2D data_types
|
||||
if target != constants::TEXTURE_2D {
|
||||
return;
|
||||
}
|
||||
if !self.extension_manager.is_get_tex_parameter_name_enabled(name) {
|
||||
return self.webgl_error(InvalidEnum);
|
||||
}
|
||||
|
||||
let target = TexImageTarget::Texture2D;
|
||||
let info = texture.image_info_for_target(&target, 0);
|
||||
if info.is_initialized() {
|
||||
self.validate_filterable_texture(&texture,
|
||||
target,
|
||||
0,
|
||||
info.internal_format().unwrap_or(TexFormat::RGBA),
|
||||
info.width(),
|
||||
info.height(),
|
||||
info.data_type().unwrap_or(TexDataType::UnsignedByte));
|
||||
}
|
||||
} else {
|
||||
self.webgl_error(InvalidOperation)
|
||||
let param = handle_potential_webgl_error!(self, TexParameter::from_u32(name), return);
|
||||
let texture = match texture {
|
||||
Some(tex) => tex,
|
||||
None => return self.webgl_error(InvalidOperation),
|
||||
};
|
||||
handle_potential_webgl_error!(self, texture.tex_parameter(param, value), return);
|
||||
|
||||
// Validate non filterable TEXTURE_2D data_types
|
||||
if target != constants::TEXTURE_2D {
|
||||
return;
|
||||
}
|
||||
|
||||
let target = TexImageTarget::Texture2D;
|
||||
let info = texture.image_info_for_target(&target, 0);
|
||||
if info.is_initialized() {
|
||||
self.validate_filterable_texture(
|
||||
&texture,
|
||||
target,
|
||||
0,
|
||||
info.internal_format().unwrap_or(TexFormat::RGBA),
|
||||
info.width(),
|
||||
info.height(),
|
||||
info.data_type().unwrap_or(TexDataType::UnsignedByte),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1437,21 +1445,16 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
#[allow(unsafe_code)]
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
|
||||
unsafe fn GetTexParameter(&self, _cx: *mut JSContext, target: u32, pname: u32) -> JSVal {
|
||||
let target_matches = match target {
|
||||
match target {
|
||||
constants::TEXTURE_2D |
|
||||
constants::TEXTURE_CUBE_MAP => true,
|
||||
_ => false,
|
||||
constants::TEXTURE_CUBE_MAP => {},
|
||||
_ => {
|
||||
self.webgl_error(InvalidEnum);
|
||||
return NullValue();
|
||||
}
|
||||
};
|
||||
|
||||
let pname_matches = match pname {
|
||||
constants::TEXTURE_MAG_FILTER |
|
||||
constants::TEXTURE_MIN_FILTER |
|
||||
constants::TEXTURE_WRAP_S |
|
||||
constants::TEXTURE_WRAP_T => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if !target_matches || !pname_matches {
|
||||
if !self.extension_manager.is_get_tex_parameter_name_enabled(pname) {
|
||||
self.webgl_error(InvalidEnum);
|
||||
return NullValue();
|
||||
}
|
||||
|
@ -1461,10 +1464,18 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
return NullValue();
|
||||
}
|
||||
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.send_command(WebGLCommand::GetTexParameter(target, pname, sender));
|
||||
|
||||
Int32Value(receiver.recv().unwrap())
|
||||
match handle_potential_webgl_error!(self, TexParameter::from_u32(pname), return NullValue()) {
|
||||
TexParameter::Float(param) => {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.send_command(WebGLCommand::GetTexParameterFloat(target, param, sender));
|
||||
DoubleValue(receiver.recv().unwrap() as f64)
|
||||
}
|
||||
TexParameter::Int(param) => {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
self.send_command(WebGLCommand::GetTexParameterInt(target, param, sender));
|
||||
Int32Value(receiver.recv().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
||||
|
||||
use canvas_traits::webgl::{webgl_channel, WebGLCommand, WebGLError, WebGLMsgSender, WebGLResult, WebGLTextureId};
|
||||
use canvas_traits::webgl::DOMToTextureCommand;
|
||||
use canvas_traits::webgl::{DOMToTextureCommand, TexParameter, TexParameterFloat};
|
||||
use canvas_traits::webgl::{TexParameterInt, WebGLCommand, WebGLError, WebGLMsgSender};
|
||||
use canvas_traits::webgl::{WebGLResult, WebGLTextureId, webgl_channel};
|
||||
use dom::bindings::cell::DomRefCell;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use dom::bindings::codegen::Bindings::WebGLTextureBinding;
|
||||
|
@ -202,65 +203,75 @@ impl WebGLTexture {
|
|||
/// We have to follow the conversion rules for GLES 2.0. See:
|
||||
/// https://www.khronos.org/webgl/public-mailing-list/archives/1008/msg00014.html
|
||||
///
|
||||
pub fn tex_parameter(&self,
|
||||
target: u32,
|
||||
name: u32,
|
||||
value: TexParameterValue) -> WebGLResult<()> {
|
||||
let (int_value, _float_value) = match value {
|
||||
pub fn tex_parameter(
|
||||
&self,
|
||||
param: TexParameter,
|
||||
value: TexParameterValue,
|
||||
) -> WebGLResult<()> {
|
||||
let target = self.target().unwrap();
|
||||
|
||||
let (int_value, float_value) = match value {
|
||||
TexParameterValue::Int(int_value) => (int_value, int_value as f32),
|
||||
TexParameterValue::Float(float_value) => (float_value as i32, float_value),
|
||||
};
|
||||
|
||||
match name {
|
||||
constants::TEXTURE_MIN_FILTER => {
|
||||
match int_value as u32 {
|
||||
constants::NEAREST |
|
||||
constants::LINEAR |
|
||||
constants::NEAREST_MIPMAP_NEAREST |
|
||||
constants::LINEAR_MIPMAP_NEAREST |
|
||||
constants::NEAREST_MIPMAP_LINEAR |
|
||||
constants::LINEAR_MIPMAP_LINEAR => {
|
||||
self.min_filter.set(Some(int_value as u32));
|
||||
self.renderer
|
||||
.send(WebGLCommand::TexParameteri(target, name, int_value))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
},
|
||||
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
match param {
|
||||
TexParameter::Int(int_param) => {
|
||||
match int_param {
|
||||
TexParameterInt::TextureMinFilter => {
|
||||
match int_value as u32 {
|
||||
constants::NEAREST |
|
||||
constants::LINEAR |
|
||||
constants::NEAREST_MIPMAP_NEAREST |
|
||||
constants::LINEAR_MIPMAP_NEAREST |
|
||||
constants::NEAREST_MIPMAP_LINEAR |
|
||||
constants::LINEAR_MIPMAP_LINEAR => {
|
||||
self.min_filter.set(Some(int_value as u32));
|
||||
self.renderer
|
||||
.send(WebGLCommand::TexParameteri(target, int_param, int_value))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
}
|
||||
}
|
||||
TexParameterInt::TextureMagFilter => {
|
||||
match int_value as u32 {
|
||||
constants::NEAREST | constants::LINEAR => {
|
||||
self.mag_filter.set(Some(int_value as u32));
|
||||
self.renderer
|
||||
.send(WebGLCommand::TexParameteri(target, int_param, int_value))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
_ => return Err(WebGLError::InvalidEnum),
|
||||
}
|
||||
}
|
||||
TexParameterInt::TextureWrapS | TexParameterInt::TextureWrapT => {
|
||||
match int_value as u32 {
|
||||
constants::CLAMP_TO_EDGE |
|
||||
constants::MIRRORED_REPEAT |
|
||||
constants::REPEAT => {
|
||||
self.renderer
|
||||
.send(WebGLCommand::TexParameteri(target, int_param, int_value))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
constants::TEXTURE_MAG_FILTER => {
|
||||
match int_value as u32 {
|
||||
constants::NEAREST |
|
||||
constants::LINEAR => {
|
||||
self.mag_filter.set(Some(int_value as u32));
|
||||
self.renderer
|
||||
.send(WebGLCommand::TexParameteri(target, name, int_value))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
},
|
||||
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
}
|
||||
TexParameter::Float(float_param @ TexParameterFloat::TextureMaxAnisotropyExt) => {
|
||||
if float_value >= 1. {
|
||||
self.renderer
|
||||
.send(WebGLCommand::TexParameterf(target, float_param, float_value))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(WebGLError::InvalidValue)
|
||||
}
|
||||
},
|
||||
constants::TEXTURE_WRAP_S |
|
||||
constants::TEXTURE_WRAP_T => {
|
||||
match int_value as u32 {
|
||||
constants::CLAMP_TO_EDGE |
|
||||
constants::MIRRORED_REPEAT |
|
||||
constants::REPEAT => {
|
||||
self.renderer
|
||||
.send(WebGLCommand::TexParameteri(target, name, int_value))
|
||||
.unwrap();
|
||||
Ok(())
|
||||
},
|
||||
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
}
|
||||
},
|
||||
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* 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 http://mozilla.org/MPL/2.0/. */
|
||||
/*
|
||||
* WebGL IDL definitions from the Khronos specification:
|
||||
* https://www.khronos.org/registry/webgl/extensions/EXT_texture_filter_anisotropic/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface EXTTextureFilterAnisotropic {
|
||||
const GLenum TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
|
||||
const GLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue