Auto merge of #21324 - servo:webgl, r=emilio

Properly set initial values for WebGL texture filters

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/21324)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2018-08-02 12:08:12 -04:00 committed by GitHub
commit c5aaae7333
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 86 additions and 76 deletions

View file

@ -276,8 +276,8 @@ pub enum WebGLCommand {
GetCurrentVertexAttrib(u32, WebGLSender<[f32; 4]>), GetCurrentVertexAttrib(u32, WebGLSender<[f32; 4]>),
GetTexParameterFloat(u32, TexParameterFloat, WebGLSender<f32>), GetTexParameterFloat(u32, TexParameterFloat, WebGLSender<f32>),
GetTexParameterInt(u32, TexParameterInt, WebGLSender<i32>), GetTexParameterInt(u32, TexParameterInt, WebGLSender<i32>),
TexParameteri(u32, TexParameterInt, i32), TexParameteri(u32, u32, i32),
TexParameterf(u32, TexParameterFloat, f32), TexParameterf(u32, u32, f32),
DrawArraysInstanced { mode: u32, first: i32, count: i32, primcount: i32 }, DrawArraysInstanced { mode: u32, first: i32, count: i32, primcount: i32 },
DrawElementsInstanced { mode: u32, count: i32, type_: u32, offset: u32, primcount: i32 }, DrawElementsInstanced { mode: u32, count: i32, type_: u32, offset: u32, primcount: i32 },
VertexAttribDivisor { index: u32, divisor: u32 }, VertexAttribDivisor { index: u32, divisor: u32 },
@ -587,8 +587,6 @@ parameters! {
TextureMaxAnisotropyExt = gl::TEXTURE_MAX_ANISOTROPY_EXT, TextureMaxAnisotropyExt = gl::TEXTURE_MAX_ANISOTROPY_EXT,
}), }),
Int(TexParameterInt { Int(TexParameterInt {
TextureMagFilter = gl::TEXTURE_MAG_FILTER,
TextureMinFilter = gl::TEXTURE_MIN_FILTER,
TextureWrapS = gl::TEXTURE_WRAP_S, TextureWrapS = gl::TEXTURE_WRAP_S,
TextureWrapT = gl::TEXTURE_WRAP_T, TextureWrapT = gl::TEXTURE_WRAP_T,
}), }),

View file

@ -446,22 +446,22 @@ impl WebGLRenderingContext {
handle_potential_webgl_error!(self, f(location)); handle_potential_webgl_error!(self, f(location));
} }
fn tex_parameter(&self, target: u32, name: u32, value: TexParameterValue) { fn tex_parameter(&self, target: u32, param: u32, value: TexParameterValue) {
let texture = match target { let texture = match target {
constants::TEXTURE_2D | constants::TEXTURE_2D |
constants::TEXTURE_CUBE_MAP => self.bound_texture(target), constants::TEXTURE_CUBE_MAP => self.bound_texture(target),
_ => return self.webgl_error(InvalidEnum), _ => return self.webgl_error(InvalidEnum),
}; };
if !self.extension_manager.is_get_tex_parameter_name_enabled(name) {
return self.webgl_error(InvalidEnum);
}
let param = handle_potential_webgl_error!(self, TexParameter::from_u32(name), return);
let texture = match texture { let texture = match texture {
Some(tex) => tex, Some(tex) => tex,
None => return self.webgl_error(InvalidOperation), None => return self.webgl_error(InvalidOperation),
}; };
if !self.extension_manager.is_get_tex_parameter_name_enabled(param) {
return self.webgl_error(InvalidEnum);
}
handle_potential_webgl_error!(self, texture.tex_parameter(param, value), return); handle_potential_webgl_error!(self, texture.tex_parameter(param, value), return);
// Validate non filterable TEXTURE_2D data_types // Validate non filterable TEXTURE_2D data_types
@ -1664,10 +1664,19 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return NullValue(); return NullValue();
} }
if self.bound_texture(target).is_none() { let texture = match self.bound_texture(target) {
Some(texture) => texture,
None => {
self.webgl_error(InvalidOperation); self.webgl_error(InvalidOperation);
return NullValue(); return NullValue();
} }
};
match pname {
constants::TEXTURE_MAG_FILTER => return UInt32Value(texture.mag_filter()),
constants::TEXTURE_MIN_FILTER => return UInt32Value(texture.min_filter()),
_ => {}
}
match handle_potential_webgl_error!(self, TexParameter::from_u32(pname), return NullValue()) { match handle_potential_webgl_error!(self, TexParameter::from_u32(pname), return NullValue()) {
TexParameter::Float(param) => { TexParameter::Float(param) => {

View file

@ -4,10 +4,10 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
use canvas_traits::webgl::{DOMToTextureCommand, TexParameter, TexParameterFloat}; use canvas_traits::webgl::{DOMToTextureCommand, WebGLCommand, WebGLError};
use canvas_traits::webgl::{TexParameterInt, WebGLCommand, WebGLError};
use canvas_traits::webgl::{WebGLResult, WebGLTextureId, webgl_channel}; use canvas_traits::webgl::{WebGLResult, WebGLTextureId, webgl_channel};
use dom::bindings::cell::DomRefCell; use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding::EXTTextureFilterAnisotropicConstants;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use dom::bindings::codegen::Bindings::WebGLTextureBinding; use dom::bindings::codegen::Bindings::WebGLTextureBinding;
use dom::bindings::inheritance::Castable; use dom::bindings::inheritance::Castable;
@ -44,8 +44,8 @@ pub struct WebGLTexture {
face_count: Cell<u8>, face_count: Cell<u8>,
base_mipmap_level: u32, base_mipmap_level: u32,
// Store information for min and mag filters // Store information for min and mag filters
min_filter: Cell<Option<u32>>, min_filter: Cell<u32>,
mag_filter: Cell<Option<u32>>, mag_filter: Cell<u32>,
/// True if this texture is used for the DOMToTexture feature. /// True if this texture is used for the DOMToTexture feature.
attached_to_dom: Cell<bool>, attached_to_dom: Cell<bool>,
} }
@ -59,8 +59,8 @@ impl WebGLTexture {
is_deleted: Cell::new(false), is_deleted: Cell::new(false),
face_count: Cell::new(0), face_count: Cell::new(0),
base_mipmap_level: 0, base_mipmap_level: 0,
min_filter: Cell::new(None), min_filter: Cell::new(constants::NEAREST_MIPMAP_LINEAR),
mag_filter: Cell::new(None), mag_filter: Cell::new(constants::LINEAR),
image_info_array: DomRefCell::new([ImageInfo::new(); MAX_LEVEL_COUNT * MAX_FACE_COUNT]), image_info_array: DomRefCell::new([ImageInfo::new(); MAX_LEVEL_COUNT * MAX_FACE_COUNT]),
attached_to_dom: Cell::new(false), attached_to_dom: Cell::new(false),
} }
@ -203,7 +203,7 @@ impl WebGLTexture {
/// ///
pub fn tex_parameter( pub fn tex_parameter(
&self, &self,
param: TexParameter, param: u32,
value: TexParameterValue, value: TexParameterValue,
) -> WebGLResult<()> { ) -> WebGLResult<()> {
let target = self.target().unwrap(); let target = self.target().unwrap();
@ -213,74 +213,77 @@ impl WebGLTexture {
TexParameterValue::Float(float_value) => (float_value as i32, float_value), TexParameterValue::Float(float_value) => (float_value as i32, float_value),
}; };
let update_filter = |filter: &Cell<u32>| {
if filter.get() == int_value as u32 {
return Ok(());
}
filter.set(int_value as u32);
self.upcast::<WebGLObject>()
.context()
.send_command(WebGLCommand::TexParameteri(target, param, int_value));
Ok(())
};
match param { match param {
TexParameter::Int(int_param) => { constants::TEXTURE_MIN_FILTER => {
match int_param {
TexParameterInt::TextureMinFilter => {
match int_value as u32 { match int_value as u32 {
constants::NEAREST | constants::NEAREST |
constants::LINEAR | constants::LINEAR |
constants::NEAREST_MIPMAP_NEAREST | constants::NEAREST_MIPMAP_NEAREST |
constants::LINEAR_MIPMAP_NEAREST | constants::LINEAR_MIPMAP_NEAREST |
constants::NEAREST_MIPMAP_LINEAR | constants::NEAREST_MIPMAP_LINEAR |
constants::LINEAR_MIPMAP_LINEAR => { constants::LINEAR_MIPMAP_LINEAR => update_filter(&self.min_filter),
self.min_filter.set(Some(int_value as u32));
self.upcast::<WebGLObject>()
.context()
.send_command(WebGLCommand::TexParameteri(target, int_param, int_value));
Ok(())
}
_ => Err(WebGLError::InvalidEnum), _ => Err(WebGLError::InvalidEnum),
} }
} }
TexParameterInt::TextureMagFilter => { constants::TEXTURE_MAG_FILTER => {
match int_value as u32 { match int_value as u32 {
constants::NEAREST | constants::LINEAR => { constants::NEAREST | constants::LINEAR => update_filter(&self.mag_filter),
self.mag_filter.set(Some(int_value as u32));
self.upcast::<WebGLObject>()
.context()
.send_command(WebGLCommand::TexParameteri(target, int_param, int_value));
Ok(())
}
_ => return Err(WebGLError::InvalidEnum), _ => return Err(WebGLError::InvalidEnum),
} }
} }
TexParameterInt::TextureWrapS | TexParameterInt::TextureWrapT => { constants::TEXTURE_WRAP_S | constants::TEXTURE_WRAP_T => {
match int_value as u32 { match int_value as u32 {
constants::CLAMP_TO_EDGE | constants::CLAMP_TO_EDGE |
constants::MIRRORED_REPEAT | constants::MIRRORED_REPEAT |
constants::REPEAT => { constants::REPEAT => {
self.upcast::<WebGLObject>() self.upcast::<WebGLObject>()
.context() .context()
.send_command(WebGLCommand::TexParameteri(target, int_param, int_value)); .send_command(WebGLCommand::TexParameteri(target, param, int_value));
Ok(()) Ok(())
} }
_ => Err(WebGLError::InvalidEnum), _ => Err(WebGLError::InvalidEnum),
} }
} }
EXTTextureFilterAnisotropicConstants::TEXTURE_MAX_ANISOTROPY_EXT => {
// NaN is not less than 1., what a time to be alive.
if !(float_value >= 1.) {
return Err(WebGLError::InvalidValue);
} }
}
TexParameter::Float(float_param @ TexParameterFloat::TextureMaxAnisotropyExt) => {
if float_value >= 1. {
self.upcast::<WebGLObject>() self.upcast::<WebGLObject>()
.context() .context()
.send_command(WebGLCommand::TexParameterf(target, float_param, float_value)); .send_command(WebGLCommand::TexParameterf(target, param, float_value));
Ok(()) Ok(())
} else { }
Err(WebGLError::InvalidValue) _ => Err(WebGLError::InvalidEnum),
} }
} }
pub fn min_filter(&self) -> u32 {
self.min_filter.get()
} }
pub fn mag_filter(&self) -> u32 {
self.mag_filter.get()
} }
pub fn is_using_linear_filtering(&self) -> bool { pub fn is_using_linear_filtering(&self) -> bool {
let filters = [self.min_filter.get(), self.mag_filter.get()]; let filters = [self.min_filter.get(), self.mag_filter.get()];
filters.iter().any(|filter| { filters.iter().any(|filter| {
match *filter { match *filter {
Some(constants::LINEAR) | constants::LINEAR |
Some(constants::NEAREST_MIPMAP_LINEAR) | constants::NEAREST_MIPMAP_LINEAR |
Some(constants::LINEAR_MIPMAP_NEAREST) | constants::LINEAR_MIPMAP_NEAREST |
Some(constants::LINEAR_MIPMAP_LINEAR) => true, constants::LINEAR_MIPMAP_LINEAR => true,
_=> false _=> false
} }
}) })