mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Add support for WebGL2 TexStorage2D
Adds initial support for the WebGL2 `TexStorage2D` call, adds support for the related texture enums and enables some of the texture tests. See: https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.6
This commit is contained in:
parent
3bedd44026
commit
8789a6a8d8
63 changed files with 1906 additions and 384 deletions
|
@ -9,7 +9,7 @@ use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
|||
use crate::dom::webgltexture::{ImageInfo, WebGLTexture};
|
||||
use crate::dom::webgltexture::{TexCompression, TexCompressionValidation};
|
||||
use canvas_traits::webgl::{TexDataType, TexFormat, WebGLError::*};
|
||||
use std::{self, fmt};
|
||||
use std::{self, cmp, fmt};
|
||||
|
||||
/// The errors that the texImage* family of functions can generate.
|
||||
#[derive(Debug)]
|
||||
|
@ -24,6 +24,10 @@ pub enum TexImageValidationError {
|
|||
NegativeLevel,
|
||||
/// A level too high to be allowed by the implementation was passed.
|
||||
LevelTooHigh,
|
||||
/// A level less than an allowed minimal value was passed.
|
||||
LevelTooLow,
|
||||
/// A depth less than an allowed minimal value was passed.
|
||||
DepthTooLow,
|
||||
/// A negative width and height was passed.
|
||||
NegativeDimension,
|
||||
/// A bigger with and height were passed than what the implementation
|
||||
|
@ -60,6 +64,8 @@ impl fmt::Display for TexImageValidationError {
|
|||
},
|
||||
NegativeLevel => "A negative level was passed",
|
||||
LevelTooHigh => "Level too high",
|
||||
LevelTooLow => "Level too low",
|
||||
DepthTooLow => "Depth too low",
|
||||
NegativeDimension => "Negative dimensions were passed",
|
||||
TextureTooBig => "Dimensions given are too big",
|
||||
InvalidDataType => "Invalid data type",
|
||||
|
@ -108,8 +114,8 @@ impl<'a> WebGLValidator for CommonTexImage2DValidator<'a> {
|
|||
// GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
// GL_TEXTURE_CUBE_MAP_POSITIVE_Z, or GL_TEXTURE_CUBE_MAP_NEGATIVE_Z.
|
||||
let target = match TexImageTarget::from_gl_constant(self.target) {
|
||||
Some(target) => target,
|
||||
None => {
|
||||
Some(target) if target.dimensions() == 2 => target,
|
||||
_ => {
|
||||
self.context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureTarget(self.target));
|
||||
},
|
||||
|
@ -140,8 +146,13 @@ impl<'a> WebGLValidator for CommonTexImage2DValidator<'a> {
|
|||
// GL_INVALID_ENUM is generated if internal_format is not an accepted
|
||||
// format.
|
||||
let internal_format = match TexFormat::from_gl_constant(self.internal_format) {
|
||||
Some(format) => format,
|
||||
None => {
|
||||
Some(format)
|
||||
if format.required_webgl_version() <= self.context.webgl_version() &&
|
||||
format.usable_as_internal() =>
|
||||
{
|
||||
format
|
||||
},
|
||||
_ => {
|
||||
self.context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureFormat);
|
||||
},
|
||||
|
@ -278,6 +289,7 @@ pub struct TexImage2DValidatorResult {
|
|||
pub border: u32,
|
||||
pub texture: DomRoot<WebGLTexture>,
|
||||
pub target: TexImageTarget,
|
||||
pub internal_format: TexFormat,
|
||||
pub format: TexFormat,
|
||||
pub data_type: TexDataType,
|
||||
}
|
||||
|
@ -303,16 +315,18 @@ impl<'a> WebGLValidator for TexImage2DValidator<'a> {
|
|||
// GL_INVALID_ENUM is generated if format or data_type is not an
|
||||
// accepted value.
|
||||
let data_type = match TexDataType::from_gl_constant(self.data_type) {
|
||||
Some(data_type) => data_type,
|
||||
None => {
|
||||
Some(data_type) if data_type.required_webgl_version() <= context.webgl_version() => {
|
||||
data_type
|
||||
},
|
||||
_ => {
|
||||
context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidDataType);
|
||||
},
|
||||
};
|
||||
|
||||
let format = match TexFormat::from_gl_constant(self.format) {
|
||||
Some(format) => format,
|
||||
None => {
|
||||
Some(format) if format.required_webgl_version() <= context.webgl_version() => format,
|
||||
_ => {
|
||||
context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureFormat);
|
||||
},
|
||||
|
@ -320,11 +334,16 @@ impl<'a> WebGLValidator for TexImage2DValidator<'a> {
|
|||
|
||||
// GL_INVALID_OPERATION is generated if format does not match
|
||||
// internal_format.
|
||||
if format != internal_format {
|
||||
if format != internal_format.to_unsized() {
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::TextureFormatMismatch);
|
||||
}
|
||||
|
||||
// NOTE: In WebGL2 data type check should be done based on the internal
|
||||
// format, but in some functions this validator is called with the
|
||||
// regular unsized format as parameter (eg. TexSubImage2D). For now
|
||||
// it's left here to avoid duplication.
|
||||
//
|
||||
// GL_INVALID_OPERATION is generated if type is
|
||||
// GL_UNSIGNED_SHORT_4_4_4_4 or GL_UNSIGNED_SHORT_5_5_5_1 and format is
|
||||
// not GL_RGBA.
|
||||
|
@ -352,6 +371,7 @@ impl<'a> WebGLValidator for TexImage2DValidator<'a> {
|
|||
border: border,
|
||||
texture: texture,
|
||||
target: target,
|
||||
internal_format: internal_format,
|
||||
format: format,
|
||||
data_type: data_type,
|
||||
})
|
||||
|
@ -657,3 +677,113 @@ impl<'a> WebGLValidator for CompressedTexSubImage2DValidator<'a> {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TexStorageValidator<'a> {
|
||||
common_validator: CommonTexImage2DValidator<'a>,
|
||||
dimensions: u8,
|
||||
depth: i32,
|
||||
}
|
||||
|
||||
pub struct TexStorageValidatorResult {
|
||||
pub texture: DomRoot<WebGLTexture>,
|
||||
pub target: TexImageTarget,
|
||||
pub levels: u32,
|
||||
pub internal_format: TexFormat,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub depth: u32,
|
||||
}
|
||||
|
||||
impl<'a> TexStorageValidator<'a> {
|
||||
pub fn new(
|
||||
context: &'a WebGLRenderingContext,
|
||||
dimensions: u8,
|
||||
target: u32,
|
||||
levels: i32,
|
||||
internal_format: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
depth: i32,
|
||||
) -> Self {
|
||||
TexStorageValidator {
|
||||
common_validator: CommonTexImage2DValidator::new(
|
||||
context,
|
||||
target,
|
||||
levels,
|
||||
internal_format,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
),
|
||||
dimensions,
|
||||
depth,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> WebGLValidator for TexStorageValidator<'a> {
|
||||
type Error = TexImageValidationError;
|
||||
type ValidatedOutput = TexStorageValidatorResult;
|
||||
|
||||
fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
|
||||
let context = self.common_validator.context;
|
||||
let CommonTexImage2DValidatorResult {
|
||||
texture,
|
||||
target,
|
||||
level,
|
||||
internal_format,
|
||||
width,
|
||||
height,
|
||||
border: _,
|
||||
} = self.common_validator.validate()?;
|
||||
|
||||
if self.depth < 1 {
|
||||
context.webgl_error(InvalidValue);
|
||||
return Err(TexImageValidationError::DepthTooLow);
|
||||
}
|
||||
if level < 1 {
|
||||
context.webgl_error(InvalidValue);
|
||||
return Err(TexImageValidationError::LevelTooLow);
|
||||
}
|
||||
|
||||
let dimensions_valid = match target {
|
||||
TexImageTarget::Texture2D | TexImageTarget::CubeMap => self.dimensions == 2,
|
||||
TexImageTarget::Texture3D | TexImageTarget::Texture2DArray => self.dimensions == 3,
|
||||
_ => false,
|
||||
};
|
||||
if !dimensions_valid {
|
||||
context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureTarget(
|
||||
target.as_gl_constant(),
|
||||
));
|
||||
}
|
||||
|
||||
if !internal_format.is_sized() {
|
||||
context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureFormat);
|
||||
}
|
||||
|
||||
let max_level = log2(cmp::max(width, height) as u32) + 1;
|
||||
if level > max_level {
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::LevelTooHigh);
|
||||
}
|
||||
|
||||
if texture.target().is_none() {
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::TextureTargetNotBound(
|
||||
target.as_gl_constant(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(TexStorageValidatorResult {
|
||||
texture,
|
||||
target,
|
||||
levels: level,
|
||||
internal_format,
|
||||
width,
|
||||
height,
|
||||
depth: self.depth as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,21 @@
|
|||
* 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 crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants;
|
||||
use canvas_traits::gl_enums;
|
||||
|
||||
gl_enums! {
|
||||
pub enum TexImageTarget {
|
||||
Texture2D = WebGLRenderingContextConstants::TEXTURE_2D,
|
||||
CubeMapPositiveX = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
CubeMapNegativeX = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
CubeMapPositiveY = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||
CubeMapNegativeY = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
CubeMapPositiveZ = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
CubeMapNegativeZ = WebGLRenderingContextConstants::TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||
Texture2D = constants::TEXTURE_2D,
|
||||
Texture2DArray = constants::TEXTURE_2D_ARRAY,
|
||||
Texture3D = constants::TEXTURE_3D,
|
||||
CubeMap = constants::TEXTURE_CUBE_MAP,
|
||||
CubeMapPositiveX = constants::TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
CubeMapNegativeX = constants::TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
CubeMapPositiveY = constants::TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||
CubeMapNegativeY = constants::TEXTURE_CUBE_MAP_NEGATIVE_Y,
|
||||
CubeMapPositiveZ = constants::TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
CubeMapNegativeZ = constants::TEXTURE_CUBE_MAP_NEGATIVE_Z,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,4 +27,11 @@ impl TexImageTarget {
|
|||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dimensions(self) -> u8 {
|
||||
match self {
|
||||
TexImageTarget::Texture3D | TexImageTarget::Texture2DArray => 3,
|
||||
_ => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue