aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <me@emiliocobos.me>2016-06-12 00:16:27 +0200
committerEmilio Cobos Álvarez <me@emiliocobos.me>2016-06-25 00:03:15 +0200
commit46c14aced2f761c39f0f602962c660e362d98416 (patch)
tree668c13ee03202b095d352f67b533b8fdac86b889 /components/script
parent8d81ee77a877f07e2d4f2779aa252f5f3bb98c7c (diff)
downloadservo-46c14aced2f761c39f0f602962c660e362d98416.tar.gz
servo-46c14aced2f761c39f0f602962c660e362d98416.zip
webgl: Refactor texture validations to take advantage of rust type system
This commit introduces the `WebGLValidator` trait, and uses it for multiple validations in the texture-related WebGL code, to move that logic out of the already bloated `webglrenderingcontext.rs` file. It also creates a type-safe wrapper for some WebGL types, removing all the `unreachable!`s there, and introduces a macro for generating them conveniently. This partially addresses #10693, pending refactor more code to use this infrastructure, and (possibly?) introducing an `AsGLError` trait for the errors to make the error handling happen in `WebGLContext`.
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/mod.rs1
-rw-r--r--components/script/dom/webgl_validations/mod.rs13
-rw-r--r--components/script/dom/webgl_validations/tex_image_2d.rs353
-rw-r--r--components/script/dom/webgl_validations/types.rs109
-rw-r--r--components/script/dom/webglrenderingcontext.rs591
-rw-r--r--components/script/dom/webgltexture.rs54
6 files changed, 706 insertions, 415 deletions
diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs
index ff1a4638998..d76721ed040 100644
--- a/components/script/dom/mod.rs
+++ b/components/script/dom/mod.rs
@@ -394,6 +394,7 @@ pub mod validation;
pub mod validitystate;
pub mod values;
pub mod virtualmethods;
+pub mod webgl_validations;
pub mod webglactiveinfo;
pub mod webglbuffer;
pub mod webglcontextevent;
diff --git a/components/script/dom/webgl_validations/mod.rs b/components/script/dom/webgl_validations/mod.rs
new file mode 100644
index 00000000000..2e070c6d6bc
--- /dev/null
+++ b/components/script/dom/webgl_validations/mod.rs
@@ -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/. */
+
+pub trait WebGLValidator {
+ type ValidatedOutput;
+ type Error: ::std::error::Error;
+
+ fn validate(self) -> Result<Self::ValidatedOutput, Self::Error>;
+}
+
+pub mod tex_image_2d;
+pub mod types;
diff --git a/components/script/dom/webgl_validations/tex_image_2d.rs b/components/script/dom/webgl_validations/tex_image_2d.rs
new file mode 100644
index 00000000000..9c4b8fa39fc
--- /dev/null
+++ b/components/script/dom/webgl_validations/tex_image_2d.rs
@@ -0,0 +1,353 @@
+/* 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 dom::bindings::js::Root;
+use dom::webglrenderingcontext::WebGLRenderingContext;
+use dom::webgltexture::WebGLTexture;
+use std::{self, fmt};
+use super::WebGLValidator;
+use super::types::{TexImageTarget, TexDataType, TexFormat};
+use webrender_traits::WebGLError::*;
+
+/// The errors that the texImage* family of functions can generate.
+#[derive(Debug)]
+pub enum TexImageValidationError {
+ /// An invalid texture target was passed, it contains the invalid target.
+ InvalidTextureTarget(u32),
+ /// The passed texture target was not bound.
+ TextureTargetNotBound(u32),
+ /// Invalid texture dimensions were given.
+ InvalidCubicTextureDimensions,
+ /// A negative level was passed.
+ NegativeLevel,
+ /// A level too high to be allowed by the implementation was passed.
+ LevelTooHigh,
+ /// A negative width and height was passed.
+ NegativeDimension,
+ /// A bigger with and height were passed than what the implementation
+ /// allows.
+ TextureTooBig,
+ /// An invalid data type was passed.
+ InvalidDataType,
+ /// An invalid texture format was passed.
+ InvalidTextureFormat,
+ /// Format did not match internal_format.
+ TextureFormatMismatch,
+ /// Invalid data type for the given format.
+ InvalidTypeForFormat,
+ /// Invalid border
+ InvalidBorder,
+ /// Expected a power of two texture.
+ NonPotTexture,
+}
+
+impl std::error::Error for TexImageValidationError {
+ fn description(&self) -> &str {
+ use self::TexImageValidationError::*;
+ match *self {
+ InvalidTextureTarget(_)
+ => "Invalid texture target",
+ TextureTargetNotBound(_)
+ => "Texture was not bound",
+ InvalidCubicTextureDimensions
+ => "Invalid dimensions were given for a cubic texture target",
+ NegativeLevel
+ => "A negative level was passed",
+ LevelTooHigh
+ => "Level too high",
+ NegativeDimension
+ => "Negative dimensions were passed",
+ TextureTooBig
+ => "Dimensions given are too big",
+ InvalidDataType
+ => "Invalid data type",
+ InvalidTextureFormat
+ => "Invalid texture format",
+ TextureFormatMismatch
+ => "Texture format mismatch",
+ InvalidTypeForFormat
+ => "Invalid type for the given format",
+ InvalidBorder
+ => "Invalid border",
+ NonPotTexture
+ => "Expected a power of two texture",
+ }
+ }
+}
+
+impl fmt::Display for TexImageValidationError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "TexImageValidationError({})", std::error::Error::description(self))
+ }
+}
+
+fn log2(n: u32) -> u32 {
+ 31 - n.leading_zeros()
+}
+
+pub struct CommonTexImage2DValidator<'a> {
+ context: &'a WebGLRenderingContext,
+ target: u32,
+ level: i32,
+ internal_format: u32,
+ width: i32,
+ height: i32,
+ border: i32,
+}
+
+pub struct CommonTexImage2DValidatorResult {
+ pub texture: Root<WebGLTexture>,
+ pub target: TexImageTarget,
+ pub level: u32,
+ pub internal_format: TexFormat,
+ pub width: u32,
+ pub height: u32,
+ pub border: u32,
+}
+
+impl<'a> WebGLValidator for CommonTexImage2DValidator<'a> {
+ type Error = TexImageValidationError;
+ type ValidatedOutput = CommonTexImage2DValidatorResult;
+ fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
+ // GL_INVALID_ENUM is generated if target is not GL_TEXTURE_2D,
+ // GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+ // 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 => {
+ self.context.webgl_error(InvalidEnum);
+ return Err(TexImageValidationError::InvalidTextureTarget(self.target));
+ }
+ };
+
+ let texture = self.context.bound_texture_for_target(&target);
+ let limits = self.context.limits();
+
+ let max_size = if target.is_cubic() {
+ limits.max_cube_map_tex_size
+ } else {
+ limits.max_tex_size
+ };
+
+ // If an attempt is made to call this function with no WebGLTexture
+ // bound, an INVALID_OPERATION error is generated.
+ let texture = match texture {
+ Some(texture) => texture,
+ None => {
+ self.context.webgl_error(InvalidOperation);
+ return Err(TexImageValidationError::TextureTargetNotBound(self.target));
+ }
+ };
+
+ // 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 => {
+ self.context.webgl_error(InvalidEnum);
+ return Err(TexImageValidationError::InvalidTextureFormat);
+ }
+ };
+
+ // GL_INVALID_VALUE is generated if level is less than 0.
+ if self.level < 0 {
+ self.context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::NegativeLevel);
+ }
+
+ // GL_INVALID_VALUE is generated if width or height is less than 0
+ if self.width < 0 || self.height < 0 {
+ self.context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::NegativeDimension);
+ }
+
+ // GL_INVALID_VALUE is generated if width or height is greater than
+ // GL_MAX_TEXTURE_SIZE when target is GL_TEXTURE_2D or
+ // GL_MAX_CUBE_MAP_TEXTURE_SIZE when target is not GL_TEXTURE_2D.
+ if self.width as u32 > max_size || self.height as u32 > max_size {
+ self.context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::TextureTooBig);
+ }
+
+ let width = self.width as u32;
+ let height = self.height as u32;
+ let level = self.level as u32;
+
+ // GL_INVALID_VALUE is generated if level is greater than zero and the
+ // texture is not power of two.
+ if level > 0 && (!width.is_power_of_two() || !height.is_power_of_two()) {
+ self.context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::NonPotTexture);
+ }
+
+ // GL_INVALID_VALUE may be generated if level is greater than
+ // log_2(max), where max is the returned value of GL_MAX_TEXTURE_SIZE
+ // when target is GL_TEXTURE_2D or GL_MAX_CUBE_MAP_TEXTURE_SIZE when
+ // target is not GL_TEXTURE_2D.
+ if level > log2(max_size) {
+ self.context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::LevelTooHigh);
+ }
+
+ // GL_INVALID_VALUE is generated if border is not 0.
+ if self.border != 0 {
+ self.context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::InvalidBorder);
+ }
+
+ Ok(CommonTexImage2DValidatorResult {
+ texture: texture,
+ target: target,
+ level: level,
+ internal_format: internal_format,
+ width: width,
+ height: height,
+ border: self.border as u32,
+ })
+ }
+}
+
+impl<'a> CommonTexImage2DValidator<'a> {
+ pub fn new(context: &'a WebGLRenderingContext,
+ target: u32, level: i32,
+ internal_format: u32,
+ width: i32, height: i32,
+ border: i32) -> Self {
+ CommonTexImage2DValidator {
+ context: context,
+ target: target,
+ level: level,
+ internal_format: internal_format,
+ width: width,
+ height: height,
+ border: border
+ }
+ }
+}
+
+pub struct TexImage2DValidator<'a> {
+ common_validator: CommonTexImage2DValidator<'a>,
+ format: u32,
+ data_type: u32,
+}
+
+impl<'a> TexImage2DValidator<'a> {
+ // TODO: Move data validation logic here.
+ pub fn new(context: &'a WebGLRenderingContext,
+ target: u32,
+ level: i32,
+ internal_format: u32,
+ width: i32,
+ height: i32,
+ border: i32,
+ format: u32,
+ data_type: u32) -> Self {
+ TexImage2DValidator {
+ common_validator: CommonTexImage2DValidator::new(context, target,
+ level,
+ internal_format,
+ width, height,
+ border),
+ format: format,
+ data_type: data_type,
+ }
+ }
+}
+
+/// The validated result of a TexImage2DValidator-validated call.
+pub struct TexImage2DValidatorResult {
+ /// NB: width, height and level are already unsigned after validation.
+ pub width: u32,
+ pub height: u32,
+ pub level: u32,
+ pub border: u32,
+ pub texture: Root<WebGLTexture>,
+ pub target: TexImageTarget,
+ pub format: TexFormat,
+ pub data_type: TexDataType,
+}
+
+/// TexImage2d validator as per
+/// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml
+impl<'a> WebGLValidator for TexImage2DValidator<'a> {
+ type ValidatedOutput = TexImage2DValidatorResult;
+ type Error = TexImageValidationError;
+
+ fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
+ let context = self.common_validator.context;
+ let CommonTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ internal_format,
+ width,
+ height,
+ border,
+ } = try!(self.common_validator.validate());
+
+ // GL_INVALID_VALUE is generated if target is one of the six cube map 2D
+ // image targets and the width and height parameters are not equal.
+ if target.is_cubic() && width != height {
+ context.webgl_error(InvalidValue);
+ return Err(TexImageValidationError::InvalidCubicTextureDimensions);
+ }
+
+ // 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 => {
+ context.webgl_error(InvalidEnum);
+ return Err(TexImageValidationError::InvalidDataType);
+ },
+ };
+
+ let format = match TexFormat::from_gl_constant(self.format) {
+ Some(format) => format,
+ None => {
+ context.webgl_error(InvalidEnum);
+ return Err(TexImageValidationError::InvalidTextureFormat);
+ }
+ };
+
+ // GL_INVALID_OPERATION is generated if format does not match
+ // internal_format.
+ if format != internal_format {
+ context.webgl_error(InvalidOperation);
+ return Err(TexImageValidationError::TextureFormatMismatch);
+ }
+
+
+ // 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.
+ //
+ // GL_INVALID_OPERATION is generated if type is GL_UNSIGNED_SHORT_5_6_5
+ // and format is not GL_RGB.
+ match data_type {
+ TexDataType::UnsignedShort4444 |
+ TexDataType::UnsignedShort5551 if format != TexFormat::RGBA => {
+ context.webgl_error(InvalidOperation);
+ return Err(TexImageValidationError::InvalidTypeForFormat);
+ },
+ TexDataType::UnsignedShort565 if format != TexFormat::RGB => {
+ context.webgl_error(InvalidOperation);
+ return Err(TexImageValidationError::InvalidTypeForFormat);
+ },
+ _ => {},
+ }
+
+ Ok(TexImage2DValidatorResult {
+ width: width,
+ height: height,
+ level: level,
+ border: border,
+ texture: texture,
+ target: target,
+ format: format,
+ data_type: data_type,
+ })
+ }
+}
diff --git a/components/script/dom/webgl_validations/types.rs b/components/script/dom/webgl_validations/types.rs
new file mode 100644
index 00000000000..f42eb548efd
--- /dev/null
+++ b/components/script/dom/webgl_validations/types.rs
@@ -0,0 +1,109 @@
+/* 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 dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
+
+/// This macro creates type-safe wrappers for WebGL types, associating variants
+/// with gl constants.
+macro_rules! type_safe_wrapper {
+ ($name: ident, $($variant:ident => $constant:ident, )+) => {
+ #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, JSTraceable, HeapSizeOf)]
+ #[repr(u32)]
+ pub enum $name {
+ $(
+ $variant = constants::$constant,
+ )+
+ }
+
+ impl $name {
+ pub fn from_gl_constant(constant: u32) -> Option<Self> {
+ Some(match constant {
+ $(constants::$constant => $name::$variant, )+
+ _ => return None,
+ })
+ }
+
+ #[inline]
+ pub fn as_gl_constant(&self) -> u32 {
+ *self as u32
+ }
+ }
+ }
+}
+
+type_safe_wrapper! { TexImageTarget,
+ Texture2D => TEXTURE_2D,
+ CubeMapPositiveX => TEXTURE_CUBE_MAP_POSITIVE_X,
+ CubeMapNegativeX => TEXTURE_CUBE_MAP_NEGATIVE_X,
+ CubeMapPositiveY => TEXTURE_CUBE_MAP_POSITIVE_Y,
+ CubeMapNegativeY => TEXTURE_CUBE_MAP_NEGATIVE_Y,
+ CubeMapPositiveZ => TEXTURE_CUBE_MAP_POSITIVE_Z,
+ CubeMapNegativeZ => TEXTURE_CUBE_MAP_NEGATIVE_Z,
+}
+
+impl TexImageTarget {
+ pub fn is_cubic(&self) -> bool {
+ match *self {
+ TexImageTarget::Texture2D => false,
+ _ => true,
+ }
+ }
+}
+
+type_safe_wrapper! { TexDataType,
+ UnsignedByte => UNSIGNED_BYTE,
+ UnsignedShort4444 => UNSIGNED_SHORT_4_4_4_4,
+ UnsignedShort5551 => UNSIGNED_SHORT_5_5_5_1,
+ UnsignedShort565 => UNSIGNED_SHORT_5_6_5,
+}
+
+impl TexDataType {
+ /// Returns the size in bytes of each element of data.
+ pub fn element_size(&self) -> u32 {
+ use self::TexDataType::*;
+ match *self {
+ UnsignedByte => 1,
+ UnsignedShort4444 |
+ UnsignedShort5551 |
+ UnsignedShort565 => 2,
+ }
+ }
+
+ /// Returns how many components a single element may hold. For example, a
+ /// UnsignedShort4444 holds four components, each with 4 bits of data.
+ pub fn components_per_element(&self) -> u32 {
+ use self::TexDataType::*;
+ match *self {
+ UnsignedByte => 1,
+ UnsignedShort565 => 3,
+ UnsignedShort5551 => 4,
+ UnsignedShort4444 => 4,
+ }
+ }
+}
+
+type_safe_wrapper! { TexFormat,
+ DepthComponent => DEPTH_COMPONENT,
+ Alpha => ALPHA,
+ RGB => RGB,
+ RGBA => RGBA,
+ Luminance => LUMINANCE,
+ LuminanceAlpha => LUMINANCE_ALPHA,
+}
+
+impl TexFormat {
+ /// Returns how many components does this format need. For example, RGBA
+ /// needs 4 components, while RGB requires 3.
+ pub fn components(&self) -> u32 {
+ use self::TexFormat::*;
+ match *self {
+ DepthComponent => 1,
+ Alpha => 1,
+ Luminance => 1,
+ LuminanceAlpha => 2,
+ RGB => 3,
+ RGBA => 4,
+ }
+ }
+}
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index b23ec913eca..46d562afa05 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -18,6 +18,10 @@ use dom::event::{Event, EventBubbles, EventCancelable};
use dom::htmlcanvaselement::HTMLCanvasElement;
use dom::htmlcanvaselement::utils as canvas_utils;
use dom::node::{Node, NodeDamage, window_from_node};
+use dom::webgl_validations::WebGLValidator;
+use dom::webgl_validations::tex_image_2d::{CommonTexImage2DValidator, CommonTexImage2DValidatorResult};
+use dom::webgl_validations::tex_image_2d::{TexImage2DValidator, TexImage2DValidatorResult};
+use dom::webgl_validations::types::{TexFormat, TexImageTarget, TexDataType};
use dom::webglactiveinfo::WebGLActiveInfo;
use dom::webglbuffer::WebGLBuffer;
use dom::webglcontextevent::WebGLContextEvent;
@@ -88,10 +92,6 @@ pub struct WebGLRenderingContext {
current_vertex_attrib_0: Cell<(f32, f32, f32, f32)>,
}
-fn log2(n: u32) -> u32 {
- 31 - n.leading_zeros()
-}
-
impl WebGLRenderingContext {
fn new_inherited(global: GlobalRef,
canvas: &HTMLCanvasElement,
@@ -141,6 +141,22 @@ impl WebGLRenderingContext {
}
}
+ pub fn limits(&self) -> &GLLimits {
+ &self.limits
+ }
+
+ pub fn bound_texture_for_target(&self, target: &TexImageTarget) -> Option<Root<WebGLTexture>> {
+ match *target {
+ TexImageTarget::Texture2D => self.bound_texture_2d.get(),
+ TexImageTarget::CubeMapPositiveX |
+ TexImageTarget::CubeMapNegativeX |
+ TexImageTarget::CubeMapPositiveY |
+ TexImageTarget::CubeMapNegativeY |
+ TexImageTarget::CubeMapPositiveZ |
+ TexImageTarget::CubeMapNegativeZ => self.bound_texture_cube_map.get(),
+ }
+ }
+
pub fn recreate(&self, size: Size2D<i32>) {
self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap();
}
@@ -239,31 +255,6 @@ impl WebGLRenderingContext {
true
}
- fn texture_for_target(&self, target: u32) -> Option<Root<WebGLTexture>> {
- match target {
- constants::TEXTURE_2D => self.bound_texture_2d.get(),
- constants::TEXTURE_CUBE_MAP_POSITIVE_X | constants::TEXTURE_CUBE_MAP_NEGATIVE_X |
- constants::TEXTURE_CUBE_MAP_POSITIVE_Y | constants::TEXTURE_CUBE_MAP_NEGATIVE_Y |
- constants::TEXTURE_CUBE_MAP_POSITIVE_Z | constants::TEXTURE_CUBE_MAP_NEGATIVE_Z => {
- self.bound_texture_cube_map.get()
- },
- _ => None,
- }
- }
-
- fn face_index_for_target(&self, target: u32) -> Option<u8> {
- match target {
- constants::TEXTURE_2D => Some(0),
- constants::TEXTURE_CUBE_MAP_POSITIVE_X => Some(0),
- constants::TEXTURE_CUBE_MAP_NEGATIVE_X => Some(1),
- constants::TEXTURE_CUBE_MAP_POSITIVE_Y => Some(2),
- constants::TEXTURE_CUBE_MAP_NEGATIVE_Y => Some(3),
- constants::TEXTURE_CUBE_MAP_POSITIVE_Z => Some(4),
- constants::TEXTURE_CUBE_MAP_NEGATIVE_Z => Some(5),
- _ => None
- }
- }
-
fn get_image_pixels(&self,
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>)
-> ImagePixelResult {
@@ -331,68 +322,18 @@ impl WebGLRenderingContext {
return Ok((pixels, size));
}
- fn validate_tex_internal_format(&self, internal_format: u32) -> bool {
- // GL_INVALID_VALUE is generated if internal_format is not an
- // accepted format.
- match internal_format {
- constants::DEPTH_COMPONENT |
- constants::ALPHA |
- constants::RGB |
- constants::RGBA |
- constants::LUMINANCE |
- constants::LUMINANCE_ALPHA => true,
-
- _ => {
- self.webgl_error(InvalidValue);
- false
- },
- }
- }
-
- fn validate_tex_format(&self, format: u32) -> bool {
- // GL_INVALID_VALUE is generated if internal_format is not an
- // accepted format.
- match format {
- constants::DEPTH_COMPONENT |
- constants::ALPHA |
- constants::RGB |
- constants::RGBA |
- constants::LUMINANCE |
- constants::LUMINANCE_ALPHA => true,
-
- _ => {
- self.webgl_error(InvalidEnum);
- false
- },
- }
- }
-
+ // TODO(emilio): Move this logic to a validator.
#[allow(unsafe_code)]
fn validate_tex_image_2d_data(&self,
- width: i32,
- height: i32,
- format: u32,
- data_type: u32,
+ width: u32,
+ height: u32,
+ format: TexFormat,
+ data_type: TexDataType,
data: Option<*mut JSObject>)
- -> Result<i32, ()> {
- // TODO(emilio, #10693): Add type-safe wrappers to validations
- let (element_size, components_per_element) = match data_type {
- constants::UNSIGNED_BYTE => (1, 1),
- constants::UNSIGNED_SHORT_5_6_5 => (2, 3),
- constants::UNSIGNED_SHORT_5_5_5_1 |
- constants::UNSIGNED_SHORT_4_4_4_4 => (2, 4),
- _ => unreachable!(), // previously validated
- };
-
- let components = match format {
- constants::DEPTH_COMPONENT => 1,
- constants::ALPHA => 1,
- constants::LUMINANCE => 1,
- constants::LUMINANCE_ALPHA => 2,
- constants::RGB => 3,
- constants::RGBA => 4,
- _ => unreachable!(), // previously validated
- };
+ -> Result<u32, ()> {
+ let element_size = data_type.element_size();
+ let components_per_element = data_type.components_per_element();
+ let components = format.components();
// If data is non-null, the type of pixels must match the type of the
// data to be read.
@@ -423,178 +364,18 @@ impl WebGLRenderingContext {
return Ok(expected_byte_length);
}
- fn validate_tex_image_2d_parameters(&self,
- target: u32,
- level: i32,
- internal_format: u32,
- width: i32,
- height: i32,
- border: i32,
- format: u32,
- data_type: u32) -> bool {
- // Validate common tex image parameters
- if !self.validate_common_tex_image_parameters(target, level, width, height) {
- return false;
- }
-
- // GL_INVALID_ENUM is generated if data_type is not an accepted value.
- match data_type {
- constants::UNSIGNED_BYTE |
- constants::UNSIGNED_SHORT_4_4_4_4 |
- constants::UNSIGNED_SHORT_5_5_5_1 |
- constants::UNSIGNED_SHORT_5_6_5 => {},
- _ => {
- self.webgl_error(InvalidEnum);
- return false;
- },
- }
- // Validate format
- if !self.validate_tex_format(format) {
- return false;
- }
-
- // Validate internal_format
- if !self.validate_tex_internal_format(internal_format) {
- return false;
- }
-
- // GL_INVALID_OPERATION is generated if format does not
- // match internal_format.
- if format != internal_format {
- self.webgl_error(InvalidOperation);
- return false;
- }
-
- // GL_INVALID_VALUE is generated if border is not 0.
- if border != 0 {
- self.webgl_error(InvalidValue);
- return false;
- }
-
- // 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.
- //
- // GL_INVALID_OPERATION is generated if type is
- // GL_UNSIGNED_SHORT_5_6_5 and format is not GL_RGB.
- match data_type {
- constants::UNSIGNED_SHORT_4_4_4_4 |
- constants::UNSIGNED_SHORT_5_5_5_1 if format != constants::RGBA => {
- self.webgl_error(InvalidOperation);
- return false;
- },
- constants::UNSIGNED_SHORT_5_6_5 if format != constants::RGB => {
- self.webgl_error(InvalidOperation);
- return false;
- },
- _ => {},
- }
-
- true
- }
-
- fn validate_common_tex_image_parameters(&self,
- target: u32,
- level: i32,
- width: i32,
- height: i32) -> bool {
- // GL_INVALID_ENUM is generated if target is not GL_TEXTURE_2D,
- // GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
- // 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.
- //
- // max_size is GL_MAX_TEXTURE_SIZE when target is GL_TEXTURE_2D or
- // GL_MAX_CUBE_MAP_TEXTURE_SIZE when target is not GL_TEXTURE_2D.
- let (texture, max) = match target {
- constants::TEXTURE_2D
- => (self.bound_texture_2d.get(), self.limits.max_tex_size),
- constants::TEXTURE_CUBE_MAP_POSITIVE_X |
- constants::TEXTURE_CUBE_MAP_NEGATIVE_X |
- constants::TEXTURE_CUBE_MAP_POSITIVE_Y |
- constants::TEXTURE_CUBE_MAP_NEGATIVE_Y |
- constants::TEXTURE_CUBE_MAP_POSITIVE_Z |
- constants::TEXTURE_CUBE_MAP_NEGATIVE_Z
- => (self.bound_texture_cube_map.get(), self.limits.max_cube_map_tex_size),
- _ => {
- self.webgl_error(InvalidEnum);
- return false;
- },
- };
-
- // If an attempt is made to call this function with no
- // WebGLTexture bound, an INVALID_OPERATION error is generated.
- if texture.is_none() {
- self.webgl_error(InvalidOperation);
- return false;
- }
-
- let is_cubic = target != constants::TEXTURE_2D;
-
- // GL_INVALID_VALUE is generated if target is one of the
- // six cube map 2D image targets and the width and height
- // parameters are not equal.
- if is_cubic && width != height {
- self.webgl_error(InvalidValue);
- return false;
- }
-
- // GL_INVALID_VALUE is generated if level is less than 0.
- //
- // GL_INVALID_VALUE is generated if width or height is less than 0
- if width < 0 || height < 0 || level < 0 ||
- width as u32 > max || height as u32 > max {
- self.webgl_error(InvalidValue);
- return false;
- }
-
- // GL_INVALID_VALUE may be generated if
- // level is greater than log_2(max), where max is
- // the returned value of GL_MAX_TEXTURE_SIZE when
- // target is GL_TEXTURE_2D or GL_MAX_CUBE_MAP_TEXTURE_SIZE
- // when target is not GL_TEXTURE_2D.
- if level > log2(max) as i32 {
- self.webgl_error(InvalidValue);
- return false;
- }
-
- // GL_INVALID_VALUE is generated if level is greater than zero and the
- // texture is not power of two.
- if level > 0 &&
- (!(width as u32).is_power_of_two() ||
- !(height as u32).is_power_of_two()) {
- self.webgl_error(InvalidValue);
- return false;
- }
-
- true
- }
-
fn tex_image_2d(&self,
- target: u32,
- level: i32,
- internal_format: u32,
- width: i32,
- height: i32,
- border: i32,
- format: u32,
- data_type: u32,
+ texture: Root<WebGLTexture>,
+ target: TexImageTarget,
+ data_type: TexDataType,
+ internal_format: TexFormat,
+ level: u32,
+ width: u32,
+ height: u32,
+ _border: u32,
pixels: Vec<u8>) { // NB: pixels should NOT be premultipied
- // This should be validated before reaching this function
- debug_assert!(self.validate_tex_image_2d_parameters(target, level,
- internal_format,
- width, height,
- border, format,
- data_type));
-
- let slot = match target {
- constants::TEXTURE_2D
- => self.bound_texture_2d.get(),
- _ => self.bound_texture_cube_map.get(),
- };
-
- let texture = slot.as_ref().expect("No bound texture found after validation");
-
- if format == constants::RGBA &&
- data_type == constants::UNSIGNED_BYTE &&
+ if internal_format == TexFormat::RGBA &&
+ data_type == TexDataType::UnsignedByte &&
self.texture_unpacking_settings.get().contains(PREMULTIPLY_ALPHA) {
// TODO(emilio): premultiply here.
}
@@ -603,15 +384,18 @@ impl WebGLRenderingContext {
// TexImage2D depth is always equal to 1
handle_potential_webgl_error!(self, texture.initialize(target,
- width as u32,
- height as u32, 1,
+ width,
+ height, 1,
internal_format,
- level as u32,
+ level,
Some(data_type)));
// TODO(emilio): Invert axis, convert colorspace, premultiply alpha if requested
- let msg = WebGLCommand::TexImage2D(target, level, internal_format as i32,
- width, height, format, data_type, pixels);
+ let msg = WebGLCommand::TexImage2D(target.as_gl_constant(), level as i32,
+ internal_format.as_gl_constant() as i32,
+ width as i32, height as i32,
+ internal_format.as_gl_constant(),
+ data_type.as_gl_constant(), pixels);
self.ipc_renderer
.send(CanvasMsg::WebGL(msg))
@@ -619,54 +403,29 @@ impl WebGLRenderingContext {
}
fn tex_sub_image_2d(&self,
- target: u32,
- level: i32,
+ texture: Root<WebGLTexture>,
+ target: TexImageTarget,
+ level: u32,
xoffset: i32,
yoffset: i32,
- width: i32,
- height: i32,
- format: u32,
- data_type: u32,
+ width: u32,
+ height: u32,
+ format: TexFormat,
+ data_type: TexDataType,
pixels: Vec<u8>) { // NB: pixels should NOT be premultipied
- // This should be validated before reaching this function
- debug_assert!(self.validate_tex_image_2d_parameters(target, level,
- format,
- width, height,
- 0, format,
- data_type));
-
- let slot = match target {
- constants::TEXTURE_2D
- => self.bound_texture_2d.get(),
- constants::TEXTURE_CUBE_MAP
- => self.bound_texture_cube_map.get(),
-
- _ => return self.webgl_error(InvalidEnum),
- };
-
- let texture = slot.as_ref().expect("No bound texture found after validation");
-
- if format == constants::RGBA &&
- data_type == constants::UNSIGNED_BYTE &&
- self.texture_unpacking_settings.get().contains(PREMULTIPLY_ALPHA) {
- // TODO(emilio): premultiply here.
- }
-
// We have already validated level
- let face_index = self.face_index_for_target(target).unwrap();
- let image_info = texture.image_info_at_face(face_index, level as u32);
+ let image_info = texture.image_info_for_target(&target, level);
// GL_INVALID_VALUE is generated if:
// - xoffset or yoffset is less than 0
// - x offset plus the width is greater than the texture width
// - y offset plus the height is greater than the texture height
- if xoffset < 0 || ((xoffset + width) as u32) > image_info.width() ||
- yoffset < 0 || ((yoffset + height) as u32) > image_info.height() {
+ if xoffset < 0 || (xoffset as u32 + width) > image_info.width() ||
+ yoffset < 0 || (yoffset as u32 + height) > image_info.height() {
return self.webgl_error(InvalidValue);
}
- // Using internal_format() to do this check
- // because we are sure format is as same as internal_format.
+ // NB: format and internal_format must match.
if format != image_info.internal_format().unwrap() ||
data_type != image_info.data_type().unwrap() {
return self.webgl_error(InvalidOperation);
@@ -675,8 +434,11 @@ impl WebGLRenderingContext {
// TODO(emilio): Flip Y axis if necessary here
// TODO(emilio): Invert axis, convert colorspace, premultiply alpha if requested
- let msg = WebGLCommand::TexSubImage2D(target, level, xoffset, yoffset,
- width, height, format, data_type, pixels);
+ let msg = WebGLCommand::TexSubImage2D(target.as_gl_constant(),
+ level as i32, xoffset, yoffset,
+ width as i32, height as i32,
+ format.as_gl_constant(),
+ data_type.as_gl_constant(), pixels);
self.ipc_renderer
.send(CanvasMsg::WebGL(msg))
@@ -1058,43 +820,39 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn CopyTexImage2D(&self, target: u32, level: i32, internal_format: u32,
x: i32, y: i32, width: i32, height: i32, border: i32) {
- // Validate common tex image parameters
- if !self.validate_common_tex_image_parameters(target, level, width, height) ||
- !self.validate_tex_internal_format(internal_format) {
- return;
- }
-
- // GL_INVALID_VALUE is generated if the border is not 0
- if border != 0 {
- self.webgl_error(InvalidValue);
- return;
- }
-
- let texture = self.texture_for_target(target).unwrap();
- let face_index = self.face_index_for_target(target).unwrap();
-
- // We have already validated level
- let image_info = texture.image_info_at_face(face_index, level as u32);
-
- // The color buffer components can be dropped during the conversion to the
- // internal_format, but new components cannot be added
- let invalid_format = match image_info.internal_format() {
- Some(src_format) => match (src_format, internal_format) {
- (constants::ALPHA, constants::ALPHA) | (constants::RGB, constants::RGB) |
- (constants::RGB, constants::LUMINANCE) | (constants::RGBA, _) => false,
- _ => true,
- },
- None => false,
+ let validator = CommonTexImage2DValidator::new(self, target, level,
+ internal_format, width,
+ height, border);
+ let CommonTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ internal_format,
+ width,
+ height,
+ border,
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return,
};
+ let image_info = texture.image_info_for_target(&target, level);
+
+ // The color buffer components can be dropped during the conversion to
+ // the internal_format, but new components cannot be added.
+ //
+ // Note that this only applies if we're copying to an already
+ // initialized texture.
+ //
// GL_INVALID_OPERATION is generated if the color buffer cannot be
- // converted to the internal_format
- if invalid_format {
- self.webgl_error(InvalidOperation);
- return;
+ // converted to the internal_format.
+ if let Some(old_internal_format) = image_info.internal_format() {
+ if old_internal_format.components() > internal_format.components() {
+ return self.webgl_error(InvalidOperation);
+ }
}
- // TexImage2D depth is always equal to 1
+ // NB: TexImage2D depth is always equal to 1
handle_potential_webgl_error!(self, texture.initialize(target,
width as u32,
height as u32, 1,
@@ -1102,8 +860,12 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
level as u32,
None));
- let msg = WebGLCommand::CopyTexImage2D(target, level, internal_format, x, y,
- width, height, border);
+ let msg = WebGLCommand::CopyTexImage2D(target.as_gl_constant(),
+ level as i32,
+ internal_format.as_gl_constant(),
+ x, y,
+ width as i32, height as i32,
+ border as i32);
self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap()
}
@@ -1111,29 +873,39 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn CopyTexSubImage2D(&self, target: u32, level: i32, xoffset: i32, yoffset: i32,
x: i32, y: i32, width: i32, height: i32) {
- // Validate common tex image parameters
- if !self.validate_common_tex_image_parameters(target, level, width, height) {
- return;
- }
-
- let texture = self.texture_for_target(target).unwrap();
- let face_index = self.face_index_for_target(target).unwrap();
+ // NB: We use a dummy (valid) format and border in order to reuse the
+ // common validations, but this should have its own validator.
+ let validator = CommonTexImage2DValidator::new(self, target, level,
+ TexFormat::RGBA.as_gl_constant(),
+ width, height, 0);
+ let CommonTexImage2DValidatorResult {
+ texture,
+ target,
+ level,
+ width,
+ height,
+ ..
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return,
+ };
- // We have already validated level
- let image_info = texture.image_info_at_face(face_index, level as u32);
+ let image_info = texture.image_info_for_target(&target, level);
// GL_INVALID_VALUE is generated if:
// - xoffset or yoffset is less than 0
// - x offset plus the width is greater than the texture width
// - y offset plus the height is greater than the texture height
- if xoffset < 0 || ((xoffset + width) as u32) > image_info.width() ||
- yoffset < 0 || ((yoffset + height) as u32) > image_info.height() {
+ if xoffset < 0 || (xoffset as u32 + width) > image_info.width() ||
+ yoffset < 0 || (yoffset as u32 + height) > image_info.height() {
self.webgl_error(InvalidValue);
return;
}
- let msg = WebGLCommand::CopyTexSubImage2D(target, level, xoffset, yoffset,
- x, y, width, height);
+ let msg = WebGLCommand::CopyTexSubImage2D(target.as_gl_constant(),
+ level as i32, xoffset, yoffset,
+ x, y,
+ width as i32, height as i32);
self.ipc_renderer.send(CanvasMsg::WebGL(msg)).unwrap();
}
@@ -2104,15 +1876,23 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
format: u32,
data_type: u32,
data: Option<*mut JSObject>) {
- if !self.validate_tex_image_2d_parameters(target,
- level,
- internal_format,
- width, height,
- border,
- format,
- data_type) {
- return; // Error handled in validate()
- }
+ let validator = TexImage2DValidator::new(self, target, level,
+ internal_format, width, height,
+ border, format, data_type);
+
+ let TexImage2DValidatorResult {
+ texture,
+ target,
+ width,
+ height,
+ level,
+ border,
+ format,
+ data_type,
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return, // NB: The validator sets the correct error for us.
+ };
let expected_byte_length = match self.validate_tex_image_2d_data(width,
height,
@@ -2136,10 +1916,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidOperation);
}
- self.tex_image_2d(target, level,
- internal_format,
- width, height, border,
- format, data_type, buff)
+ self.tex_image_2d(texture, target, data_type, format,
+ level, width, height, border, buff)
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@@ -2156,17 +1934,28 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Err(_) => return,
};
- // NB: Border must be zero
- if !self.validate_tex_image_2d_parameters(target, level, internal_format,
- size.width, size.height, 0,
- format, data_type) {
- return; // Error handled in validate()
- }
- self.tex_image_2d(target, level,
- internal_format,
- size.width, size.height, 0,
- format, data_type, pixels);
+ let validator = TexImage2DValidator::new(self,
+ target, level, internal_format,
+ size.width, size.height,
+ 0, format, data_type);
+
+ let TexImage2DValidatorResult {
+ texture,
+ target,
+ width,
+ height,
+ level,
+ border,
+ format,
+ data_type,
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return, // NB: The validator sets the correct error for us.
+ };
+
+ self.tex_image_2d(texture, target, data_type, format,
+ level, width, height, border, pixels);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@@ -2181,15 +1970,22 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
format: u32,
data_type: u32,
data: Option<*mut JSObject>) {
- if !self.validate_tex_image_2d_parameters(target,
- level,
- format,
- width, height,
- 0,
- format,
- data_type) {
- return; // Error handled in validate()
- }
+ let validator = TexImage2DValidator::new(self, target, level,
+ format, width, height,
+ 0, format, data_type);
+ let TexImage2DValidatorResult {
+ texture,
+ target,
+ width,
+ height,
+ level,
+ format,
+ data_type,
+ ..
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return, // NB: The validator sets the correct error for us.
+ };
let expected_byte_length = match self.validate_tex_image_2d_data(width,
height,
@@ -2214,10 +2010,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
return self.webgl_error(InvalidOperation);
}
- self.tex_sub_image_2d(target, level,
- xoffset, yoffset,
- width, height,
- format, data_type, buff);
+ self.tex_sub_image_2d(texture, target, level, xoffset, yoffset,
+ width, height, format, data_type, buff);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
@@ -2229,23 +2023,30 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
format: u32,
data_type: u32,
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) {
- // Get pixels from image source
let (pixels, size) = match self.get_image_pixels(source) {
Ok((pixels, size)) => (pixels, size),
Err(_) => return,
};
- // NB: Border must be zero
- if !self.validate_tex_image_2d_parameters(target, level, format,
- size.width, size.height, 0,
- format, data_type) {
- return; // Error handled in validate()
- }
+ let validator = TexImage2DValidator::new(self, target, level, format,
+ size.width, size.height,
+ 0, format, data_type);
+ let TexImage2DValidatorResult {
+ texture,
+ target,
+ width,
+ height,
+ level,
+ format,
+ data_type,
+ ..
+ } = match validator.validate() {
+ Ok(result) => result,
+ Err(_) => return, // NB: The validator sets the correct error for us.
+ };
- self.tex_sub_image_2d(target, level,
- xoffset, yoffset,
- size.width, size.height,
- format, data_type, pixels);
+ self.tex_sub_image_2d(texture, target, level, xoffset, yoffset,
+ width, height, format, data_type, pixels);
}
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs
index bd9f34515ba..647b36ddfe7 100644
--- a/components/script/dom/webgltexture.rs
+++ b/components/script/dom/webgltexture.rs
@@ -10,6 +10,7 @@ use dom::bindings::codegen::Bindings::WebGLTextureBinding;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root;
use dom::bindings::reflector::reflect_dom_object;
+use dom::webgl_validations::types::{TexImageTarget, TexFormat, TexDataType};
use dom::webglobject::WebGLObject;
use ipc_channel::ipc::{self, IpcSender};
use std::cell::Cell;
@@ -104,13 +105,13 @@ impl WebGLTexture {
}
pub fn initialize(&self,
- target: u32,
+ target: TexImageTarget,
width: u32,
height: u32,
depth: u32,
- internal_format: u32,
+ internal_format: TexFormat,
level: u32,
- data_type: Option<u32>) -> WebGLResult<()> {
+ data_type: Option<TexDataType>) -> WebGLResult<()> {
let image_info = ImageInfo {
width: width,
height: height,
@@ -120,17 +121,8 @@ impl WebGLTexture {
data_type: data_type,
};
- let face = match target {
- constants::TEXTURE_2D | constants::TEXTURE_CUBE_MAP_POSITIVE_X => 0,
- constants::TEXTURE_CUBE_MAP_NEGATIVE_X => 1,
- constants::TEXTURE_CUBE_MAP_POSITIVE_Y => 2,
- constants::TEXTURE_CUBE_MAP_NEGATIVE_Y => 3,
- constants::TEXTURE_CUBE_MAP_POSITIVE_Z => 4,
- constants::TEXTURE_CUBE_MAP_NEGATIVE_Z => 5,
- _ => unreachable!(),
- };
-
- self.set_image_infos_at_level_and_face(level, face, image_info);
+ let face_index = self.face_index_for_target(&target);
+ self.set_image_infos_at_level_and_face(level, face_index, image_info);
Ok(())
}
@@ -312,7 +304,27 @@ impl WebGLTexture {
true
}
- pub fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo {
+ fn face_index_for_target(&self,
+ target: &TexImageTarget) -> u8 {
+ match *target {
+ TexImageTarget::Texture2D => 0,
+ TexImageTarget::CubeMapPositiveX => 0,
+ TexImageTarget::CubeMapNegativeX => 1,
+ TexImageTarget::CubeMapPositiveY => 2,
+ TexImageTarget::CubeMapNegativeY => 3,
+ TexImageTarget::CubeMapPositiveZ => 4,
+ TexImageTarget::CubeMapNegativeZ => 5,
+ }
+ }
+
+ pub fn image_info_for_target(&self,
+ target: &TexImageTarget,
+ level: u32) -> ImageInfo {
+ let face_index = self.face_index_for_target(&target);
+ self.image_info_at_face(face_index, level)
+ }
+
+ fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo {
let pos = (level * self.face_count.get() as u32) + face as u32;
self.image_info_array.borrow()[pos as usize]
}
@@ -347,9 +359,9 @@ pub struct ImageInfo {
width: u32,
height: u32,
depth: u32,
- internal_format: Option<u32>,
+ internal_format: Option<TexFormat>,
is_initialized: bool,
- data_type: Option<u32>,
+ data_type: Option<TexDataType>,
}
impl ImageInfo {
@@ -372,16 +384,18 @@ impl ImageInfo {
self.height
}
- pub fn internal_format(&self) -> Option<u32> {
+ pub fn internal_format(&self) -> Option<TexFormat> {
self.internal_format
}
- pub fn data_type(&self) -> Option<u32> {
+ pub fn data_type(&self) -> Option<TexDataType> {
self.data_type
}
fn is_power_of_two(&self) -> bool {
- self.width.is_power_of_two() && self.height.is_power_of_two() && self.depth.is_power_of_two()
+ self.width.is_power_of_two() &&
+ self.height.is_power_of_two() &&
+ self.depth.is_power_of_two()
}
fn is_initialized(&self) -> bool {