mirror of
https://github.com/servo/servo.git
synced 2025-07-15 03:13:41 +01:00
WebGL2: support TexImage3D (#37718)
Add TexImage3D method to WebGL2RenderingContext Testing: conformance2 should pass. Also it should get http://webglsamples.org/WebGL2Samples/#texture_2d_array and http://webglsamples.org/WebGL2Samples/#texture_3d running. Fixes: #26511 Now Servo can run texture_2d_array and texture_3d samples!   And it can now run three.js too!  --------- Signed-off-by: Wu Yu Wei <yuweiwu@pm.me>
This commit is contained in:
parent
4499fdeb2b
commit
34c31ee418
43 changed files with 1341 additions and 980 deletions
|
@ -11,8 +11,8 @@ use std::rc::Rc;
|
|||
use bitflags::bitflags;
|
||||
use canvas_traits::webgl::WebGLError::*;
|
||||
use canvas_traits::webgl::{
|
||||
GLContextAttributes, InternalFormatParameter, WebGLCommand, WebGLContextId, WebGLResult,
|
||||
WebGLVersion, webgl_channel,
|
||||
AlphaTreatment, GLContextAttributes, InternalFormatParameter, TexDataType, TexFormat,
|
||||
WebGLCommand, WebGLContextId, WebGLResult, WebGLVersion, YAxisTreatment, webgl_channel,
|
||||
};
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
|
@ -27,6 +27,7 @@ use servo_config::pref;
|
|||
use url::Host;
|
||||
use webrender_api::ImageKey;
|
||||
|
||||
use super::webgl_validations::types::TexImageTarget;
|
||||
use crate::canvas_context::CanvasContext;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::{
|
||||
WebGL2RenderingContextConstants as constants, WebGL2RenderingContextMethods,
|
||||
|
@ -51,6 +52,7 @@ use crate::dom::webgl_validations::WebGLValidator;
|
|||
use crate::dom::webgl_validations::tex_image_2d::{
|
||||
TexImage2DValidator, TexImage2DValidatorResult, TexStorageValidator, TexStorageValidatorResult,
|
||||
};
|
||||
use crate::dom::webgl_validations::tex_image_3d::{TexImage3DValidator, TexImage3DValidatorResult};
|
||||
use crate::dom::webglactiveinfo::WebGLActiveInfo;
|
||||
use crate::dom::webglbuffer::WebGLBuffer;
|
||||
use crate::dom::webglframebuffer::{WebGLFramebuffer, WebGLFramebufferAttachmentRoot};
|
||||
|
@ -899,6 +901,66 @@ impl WebGL2RenderingContext {
|
|||
texture.storage(target, levels, internal_format, width, height, depth)
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn tex_image_3d(
|
||||
&self,
|
||||
texture: &WebGLTexture,
|
||||
target: TexImageTarget,
|
||||
data_type: TexDataType,
|
||||
internal_format: TexFormat,
|
||||
format: TexFormat,
|
||||
level: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
depth: u32,
|
||||
_border: u32,
|
||||
unpacking_alignment: u32,
|
||||
data: TexPixels,
|
||||
) {
|
||||
handle_potential_webgl_error!(
|
||||
self.base,
|
||||
texture.initialize(
|
||||
target,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
internal_format,
|
||||
level,
|
||||
Some(data_type)
|
||||
)
|
||||
);
|
||||
|
||||
let internal_format = self
|
||||
.base
|
||||
.extension_manager()
|
||||
.get_effective_tex_internal_format(internal_format, data_type.as_gl_constant());
|
||||
let effective_data_type = self
|
||||
.base
|
||||
.extension_manager()
|
||||
.effective_type(data_type.as_gl_constant());
|
||||
|
||||
self.base.send_command(WebGLCommand::TexImage3D {
|
||||
target: target.as_gl_constant(),
|
||||
level,
|
||||
internal_format,
|
||||
size: data.size(),
|
||||
depth,
|
||||
format,
|
||||
data_type,
|
||||
effective_data_type,
|
||||
unpacking_alignment,
|
||||
alpha_treatment: data.alpha_treatment(),
|
||||
y_axis_treatment: data.y_axis_treatment(),
|
||||
pixel_format: data.pixel_format(),
|
||||
data: data.into_shared_memory().into(),
|
||||
});
|
||||
// TODO: Hint/tex_parameter
|
||||
|
||||
if let Some(fb) = self.base.bound_draw_framebuffer() {
|
||||
fb.invalidate_texture(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CanvasContext for WebGL2RenderingContext {
|
||||
|
@ -2344,6 +2406,8 @@ impl WebGL2RenderingContextMethods<crate::DomTypeHolder> for WebGL2RenderingCont
|
|||
constants::BOOL |
|
||||
constants::UNSIGNED_INT |
|
||||
constants::SAMPLER_2D |
|
||||
constants::SAMPLER_2D_ARRAY |
|
||||
constants::SAMPLER_3D |
|
||||
constants::SAMPLER_CUBE => {},
|
||||
_ => return Err(InvalidOperation),
|
||||
}
|
||||
|
@ -2992,6 +3056,136 @@ impl WebGL2RenderingContextMethods<crate::DomTypeHolder> for WebGL2RenderingCont
|
|||
self.base.Viewport(x, y, width, height)
|
||||
}
|
||||
|
||||
/// <https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.7.6>
|
||||
///
|
||||
/// Allocates and initializes the specified mipmap level of a three-dimensional or
|
||||
/// two-dimensional array texture.
|
||||
#[allow(unsafe_code)]
|
||||
fn TexImage3D(
|
||||
&self,
|
||||
target: u32,
|
||||
level: i32,
|
||||
internal_format: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
depth: i32,
|
||||
border: i32,
|
||||
format: u32,
|
||||
type_: u32,
|
||||
src_data: CustomAutoRooterGuard<Option<ArrayBufferView>>,
|
||||
) -> Fallible<()> {
|
||||
// If a WebGLBuffer is bound to the PIXEL_UNPACK_BUFFER target,
|
||||
// generates an INVALID_OPERATION error.
|
||||
if self.bound_pixel_unpack_buffer.get().is_some() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// If type is specified as FLOAT_32_UNSIGNED_INT_24_8_REV, srcData must be null;
|
||||
// otherwise, generates an INVALID_OPERATION error.
|
||||
if type_ == constants::FLOAT_32_UNSIGNED_INT_24_8_REV && src_data.is_some() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if border != 0 {
|
||||
self.base.webgl_error(InvalidValue);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Ok(TexImage3DValidatorResult {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
level,
|
||||
border,
|
||||
texture,
|
||||
target,
|
||||
internal_format,
|
||||
format,
|
||||
data_type,
|
||||
}) = TexImage3DValidator::new(
|
||||
&self.base,
|
||||
target,
|
||||
level,
|
||||
internal_format as u32,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
border,
|
||||
format,
|
||||
type_,
|
||||
&src_data,
|
||||
)
|
||||
.validate()
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// TODO: If pixel store parameter constraints are not met, generates an INVALID_OPERATION error.
|
||||
|
||||
// If srcData is null, a buffer of sufficient size initialized to 0 is passed.
|
||||
let unpacking_alignment = self.base.texture_unpacking_alignment();
|
||||
let buff = match *src_data {
|
||||
Some(ref data) => IpcSharedMemory::from_bytes(unsafe { data.as_slice() }),
|
||||
None => {
|
||||
let element_size = data_type.element_size();
|
||||
let components = format.components();
|
||||
let components_per_element = format.components();
|
||||
// FIXME: This is copied from tex_image_2d which is apparently incorrect
|
||||
// NOTE: width and height are positive or zero due to validate()
|
||||
let expected_byte_len = if height == 0 {
|
||||
0
|
||||
} else {
|
||||
// We need to be careful here to not count unpack
|
||||
// alignment at the end of the image, otherwise (for
|
||||
// example) passing a single byte for uploading a 1x1
|
||||
// GL_ALPHA/GL_UNSIGNED_BYTE texture would throw an error.
|
||||
let cpp = element_size * components / components_per_element;
|
||||
let stride =
|
||||
(width * cpp + unpacking_alignment - 1) & !(unpacking_alignment - 1);
|
||||
stride * (height - 1) + width * cpp
|
||||
};
|
||||
IpcSharedMemory::from_bytes(&vec![0u8; expected_byte_len as usize])
|
||||
},
|
||||
};
|
||||
let (alpha_treatment, y_axis_treatment) =
|
||||
self.base.get_current_unpack_state(Alpha::NotPremultiplied);
|
||||
// If UNPACK_FLIP_Y_WEBGL or UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to true, texImage3D and texSubImage3D
|
||||
// generate an INVALID_OPERATION error if they upload data from a PIXEL_UNPACK_BUFFER or a non-null client
|
||||
// side ArrayBufferView.
|
||||
if let (Some(AlphaTreatment::Premultiply), YAxisTreatment::Flipped) =
|
||||
(alpha_treatment, y_axis_treatment)
|
||||
{
|
||||
if src_data.is_some() {
|
||||
self.base.webgl_error(InvalidOperation);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
let tex_source = TexPixels::from_array(
|
||||
buff,
|
||||
Size2D::new(width, height),
|
||||
alpha_treatment,
|
||||
y_axis_treatment,
|
||||
);
|
||||
|
||||
self.tex_image_3d(
|
||||
&texture,
|
||||
target,
|
||||
data_type,
|
||||
internal_format,
|
||||
format,
|
||||
level,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
border,
|
||||
unpacking_alignment,
|
||||
tex_source,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// <https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8>
|
||||
fn TexImage2D(
|
||||
&self,
|
||||
|
|
|
@ -10,4 +10,5 @@ pub(crate) trait WebGLValidator {
|
|||
}
|
||||
|
||||
pub(crate) mod tex_image_2d;
|
||||
pub(crate) mod tex_image_3d;
|
||||
pub(crate) mod types;
|
||||
|
|
311
components/script/dom/webgl_validations/tex_image_3d.rs
Normal file
311
components/script/dom/webgl_validations/tex_image_3d.rs
Normal file
|
@ -0,0 +1,311 @@
|
|||
/* 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 canvas_traits::webgl::WebGLError::*;
|
||||
use canvas_traits::webgl::{TexDataType, TexFormat};
|
||||
use js::jsapi::Type;
|
||||
use js::typedarray::ArrayBufferView;
|
||||
|
||||
use super::WebGLValidator;
|
||||
use super::tex_image_2d::TexImageValidationError;
|
||||
use super::types::TexImageTarget;
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::dom::webgltexture::WebGLTexture;
|
||||
|
||||
fn log2(n: u32) -> u32 {
|
||||
31 - n.leading_zeros()
|
||||
}
|
||||
|
||||
pub(crate) struct CommonTexImage3DValidator<'a> {
|
||||
context: &'a WebGLRenderingContext,
|
||||
target: u32,
|
||||
level: i32,
|
||||
internal_format: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
depth: i32,
|
||||
border: i32,
|
||||
}
|
||||
|
||||
pub(crate) struct CommonTexImage3DValidatorResult {
|
||||
pub(crate) texture: DomRoot<WebGLTexture>,
|
||||
pub(crate) target: TexImageTarget,
|
||||
pub(crate) level: u32,
|
||||
pub(crate) internal_format: TexFormat,
|
||||
pub(crate) width: u32,
|
||||
pub(crate) height: u32,
|
||||
pub(crate) depth: u32,
|
||||
pub(crate) border: u32,
|
||||
}
|
||||
|
||||
impl WebGLValidator for CommonTexImage3DValidator<'_> {
|
||||
type Error = TexImageValidationError;
|
||||
type ValidatedOutput = CommonTexImage3DValidatorResult;
|
||||
fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
|
||||
// GL_INVALID_ENUM is generated if target is not GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY.
|
||||
let target = match TexImageTarget::from_gl_constant(self.target) {
|
||||
Some(target) if target.dimensions() == 3 => target,
|
||||
_ => {
|
||||
self.context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureTarget(self.target));
|
||||
},
|
||||
};
|
||||
|
||||
let texture = self
|
||||
.context
|
||||
.textures()
|
||||
.active_texture_for_image_target(target);
|
||||
let limits = self.context.limits();
|
||||
|
||||
let max_size = limits.max_3d_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)
|
||||
if format.required_webgl_version() <= self.context.webgl_version() &&
|
||||
format.usable_as_internal() =>
|
||||
{
|
||||
format
|
||||
},
|
||||
_ => {
|
||||
self.context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureFormat);
|
||||
},
|
||||
};
|
||||
|
||||
// GL_INVALID_VALUE is generated if width, height, or depth is less than 0 or greater than
|
||||
// GL_MAX_3D_TEXTURE_SIZE.
|
||||
if self.width < 0 || self.height < 0 || self.depth < 0 {
|
||||
self.context.webgl_error(InvalidValue);
|
||||
return Err(TexImageValidationError::NegativeDimension);
|
||||
}
|
||||
let width = self.width as u32;
|
||||
let height = self.height as u32;
|
||||
let depth = self.depth as u32;
|
||||
let level = self.level as u32;
|
||||
if width > max_size || height > max_size || level > max_size {
|
||||
self.context.webgl_error(InvalidValue);
|
||||
return Err(TexImageValidationError::TextureTooBig);
|
||||
}
|
||||
|
||||
// GL_INVALID_VALUE may be generated if level is greater than log2(max),
|
||||
// where max is the returned value of GL_MAX_3D_TEXTURE_SIZE.
|
||||
if self.level < 0 {
|
||||
self.context.webgl_error(InvalidValue);
|
||||
return Err(TexImageValidationError::NegativeLevel);
|
||||
}
|
||||
if level > log2(max_size) {
|
||||
self.context.webgl_error(InvalidValue);
|
||||
return Err(TexImageValidationError::LevelTooHigh);
|
||||
}
|
||||
|
||||
// GL_INVALID_VALUE is generated if border is not 0 or 1.
|
||||
if !(self.border == 0 || self.border == 1) {
|
||||
self.context.webgl_error(InvalidValue);
|
||||
return Err(TexImageValidationError::InvalidBorder);
|
||||
}
|
||||
|
||||
Ok(CommonTexImage3DValidatorResult {
|
||||
texture,
|
||||
target,
|
||||
level,
|
||||
internal_format,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
border: self.border as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> CommonTexImage3DValidator<'a> {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
context: &'a WebGLRenderingContext,
|
||||
target: u32,
|
||||
level: i32,
|
||||
internal_format: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
depth: i32,
|
||||
border: i32,
|
||||
) -> Self {
|
||||
CommonTexImage3DValidator {
|
||||
context,
|
||||
target,
|
||||
level,
|
||||
internal_format,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
border,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct TexImage3DValidator<'a> {
|
||||
common_validator: CommonTexImage3DValidator<'a>,
|
||||
format: u32,
|
||||
data_type: u32,
|
||||
data: &'a Option<ArrayBufferView>,
|
||||
}
|
||||
|
||||
impl<'a> TexImage3DValidator<'a> {
|
||||
/// TODO: Move data validation logic here.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn new(
|
||||
context: &'a WebGLRenderingContext,
|
||||
target: u32,
|
||||
level: i32,
|
||||
internal_format: u32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
depth: i32,
|
||||
border: i32,
|
||||
format: u32,
|
||||
data_type: u32,
|
||||
data: &'a Option<ArrayBufferView>,
|
||||
) -> Self {
|
||||
TexImage3DValidator {
|
||||
common_validator: CommonTexImage3DValidator::new(
|
||||
context,
|
||||
target,
|
||||
level,
|
||||
internal_format,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
border,
|
||||
),
|
||||
format,
|
||||
data_type,
|
||||
data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The validated result of a TexImage2DValidator-validated call.
|
||||
pub(crate) struct TexImage3DValidatorResult {
|
||||
/// NB: width, height and level are already unsigned after validation.
|
||||
pub(crate) width: u32,
|
||||
pub(crate) height: u32,
|
||||
pub(crate) depth: u32,
|
||||
pub(crate) level: u32,
|
||||
pub(crate) border: u32,
|
||||
pub(crate) texture: DomRoot<WebGLTexture>,
|
||||
pub(crate) target: TexImageTarget,
|
||||
pub(crate) internal_format: TexFormat,
|
||||
pub(crate) format: TexFormat,
|
||||
pub(crate) data_type: TexDataType,
|
||||
}
|
||||
|
||||
/// TexImage3d validator as per
|
||||
/// <https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage3D.xml>
|
||||
impl WebGLValidator for TexImage3DValidator<'_> {
|
||||
type ValidatedOutput = TexImage3DValidatorResult;
|
||||
type Error = TexImageValidationError;
|
||||
|
||||
fn validate(self) -> Result<Self::ValidatedOutput, TexImageValidationError> {
|
||||
let context = self.common_validator.context;
|
||||
let CommonTexImage3DValidatorResult {
|
||||
texture,
|
||||
target,
|
||||
level,
|
||||
internal_format,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
border,
|
||||
} = self.common_validator.validate()?;
|
||||
|
||||
// GL_INVALID_ENUM is generated if format is not an accepted format constant.
|
||||
// Format constants other than GL_STENCIL_INDEX and GL_DEPTH_COMPONENT are accepted.
|
||||
let data_type = match TexDataType::from_gl_constant(self.data_type) {
|
||||
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) if format.required_webgl_version() <= context.webgl_version() => format,
|
||||
_ => {
|
||||
context.webgl_error(InvalidEnum);
|
||||
return Err(TexImageValidationError::InvalidTextureFormat);
|
||||
},
|
||||
};
|
||||
|
||||
// GL_INVALID_OPERATION is generated if format does not match
|
||||
// internal_format.
|
||||
if format != internal_format.to_unsized() {
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::TextureFormatMismatch);
|
||||
}
|
||||
|
||||
if !internal_format.compatible_data_types().contains(&data_type) {
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::TextureFormatMismatch);
|
||||
}
|
||||
|
||||
// GL_INVALID_OPERATION is generated if target is GL_TEXTURE_3D and
|
||||
// format is GL_DEPTH_COMPONENT, or GL_DEPTH_STENCIL.
|
||||
if target == TexImageTarget::Texture3D &&
|
||||
(format == TexFormat::DepthComponent || format == TexFormat::DepthStencil)
|
||||
{
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::InvalidTypeForFormat);
|
||||
}
|
||||
|
||||
// If srcData is non-null, the type of srcData must match the type according to
|
||||
// the above table; otherwise, generate an INVALID_OPERATION error.
|
||||
let element_size = data_type.element_size();
|
||||
let received_size = match self.data {
|
||||
Some(buf) => match buf.get_array_type() {
|
||||
Type::Int8 => 1,
|
||||
Type::Uint8 => 1,
|
||||
Type::Int16 => 2,
|
||||
Type::Uint16 => 2,
|
||||
Type::Int32 => 4,
|
||||
Type::Uint32 => 4,
|
||||
Type::Float32 => 4,
|
||||
_ => {
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::InvalidTypeForFormat);
|
||||
},
|
||||
},
|
||||
None => element_size,
|
||||
};
|
||||
if received_size != element_size {
|
||||
context.webgl_error(InvalidOperation);
|
||||
return Err(TexImageValidationError::InvalidTypeForFormat);
|
||||
}
|
||||
|
||||
Ok(TexImage3DValidatorResult {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
level,
|
||||
border,
|
||||
texture,
|
||||
target,
|
||||
internal_format,
|
||||
format,
|
||||
data_type,
|
||||
})
|
||||
}
|
||||
}
|
|
@ -143,7 +143,7 @@ pub(crate) unsafe fn uniform_typed<T>(
|
|||
|
||||
/// Set of bitflags for texture unpacking (texImage2d, etc...)
|
||||
#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
|
||||
struct TextureUnpacking(u8);
|
||||
pub(crate) struct TextureUnpacking(u8);
|
||||
|
||||
bitflags! {
|
||||
impl TextureUnpacking: u8 {
|
||||
|
@ -327,6 +327,10 @@ impl WebGLRenderingContext {
|
|||
self.texture_unpacking_alignment.get()
|
||||
}
|
||||
|
||||
pub(crate) fn bound_draw_framebuffer(&self) -> Option<DomRoot<WebGLFramebuffer>> {
|
||||
self.bound_draw_framebuffer.get()
|
||||
}
|
||||
|
||||
pub(crate) fn current_vao(&self) -> DomRoot<WebGLVertexArrayObjectOES> {
|
||||
self.current_vao.or_init(|| {
|
||||
DomRoot::from_ref(
|
||||
|
@ -1680,6 +1684,8 @@ impl WebGLRenderingContext {
|
|||
constants::BOOL |
|
||||
constants::INT |
|
||||
constants::SAMPLER_2D |
|
||||
WebGL2RenderingContextConstants::SAMPLER_2D_ARRAY |
|
||||
WebGL2RenderingContextConstants::SAMPLER_3D |
|
||||
constants::SAMPLER_CUBE => {},
|
||||
_ => return Err(InvalidOperation),
|
||||
}
|
||||
|
@ -1687,7 +1693,10 @@ impl WebGLRenderingContext {
|
|||
let val = self.uniform_vec_section_int(val, src_offset, src_length, 1, location)?;
|
||||
|
||||
match location.type_() {
|
||||
constants::SAMPLER_2D | constants::SAMPLER_CUBE => {
|
||||
constants::SAMPLER_2D |
|
||||
constants::SAMPLER_CUBE |
|
||||
WebGL2RenderingContextConstants::SAMPLER_2D_ARRAY |
|
||||
WebGL2RenderingContextConstants::SAMPLER_3D => {
|
||||
for &v in val
|
||||
.iter()
|
||||
.take(cmp::min(location.size().unwrap_or(1) as usize, val.len()))
|
||||
|
@ -2149,6 +2158,30 @@ impl WebGLRenderingContextMethods<crate::DomTypeHolder> for WebGLRenderingContex
|
|||
texture.to_jsval(*cx, retval);
|
||||
return;
|
||||
},
|
||||
WebGL2RenderingContextConstants::TEXTURE_BINDING_2D_ARRAY => unsafe {
|
||||
let texture = self
|
||||
.textures
|
||||
.active_texture_slot(
|
||||
WebGL2RenderingContextConstants::TEXTURE_2D_ARRAY,
|
||||
self.webgl_version(),
|
||||
)
|
||||
.unwrap()
|
||||
.get();
|
||||
texture.to_jsval(*cx, retval);
|
||||
return;
|
||||
},
|
||||
WebGL2RenderingContextConstants::TEXTURE_BINDING_3D => unsafe {
|
||||
let texture = self
|
||||
.textures
|
||||
.active_texture_slot(
|
||||
WebGL2RenderingContextConstants::TEXTURE_3D,
|
||||
self.webgl_version(),
|
||||
)
|
||||
.unwrap()
|
||||
.get();
|
||||
texture.to_jsval(*cx, retval);
|
||||
return;
|
||||
},
|
||||
constants::TEXTURE_BINDING_CUBE_MAP => unsafe {
|
||||
let texture = self
|
||||
.textures
|
||||
|
@ -4036,7 +4069,10 @@ impl WebGLRenderingContextMethods<crate::DomTypeHolder> for WebGLRenderingContex
|
|||
self.with_location(location, |location| {
|
||||
match location.type_() {
|
||||
constants::BOOL | constants::INT => {},
|
||||
constants::SAMPLER_2D | constants::SAMPLER_CUBE => {
|
||||
constants::SAMPLER_2D |
|
||||
WebGL2RenderingContextConstants::SAMPLER_3D |
|
||||
WebGL2RenderingContextConstants::SAMPLER_2D_ARRAY |
|
||||
constants::SAMPLER_CUBE => {
|
||||
if val < 0 || val as u32 >= self.limits.max_combined_texture_image_units {
|
||||
return Err(InvalidValue);
|
||||
}
|
||||
|
@ -4237,7 +4273,11 @@ impl WebGLRenderingContextMethods<crate::DomTypeHolder> for WebGLRenderingContex
|
|||
constants::BOOL_VEC4 => unsafe {
|
||||
uniform_get(triple, WebGLCommand::GetUniformBool4).to_jsval(*cx, rval);
|
||||
},
|
||||
constants::INT | constants::SAMPLER_2D | constants::SAMPLER_CUBE => {
|
||||
constants::INT |
|
||||
constants::SAMPLER_2D |
|
||||
constants::SAMPLER_CUBE |
|
||||
WebGL2RenderingContextConstants::SAMPLER_2D_ARRAY |
|
||||
WebGL2RenderingContextConstants::SAMPLER_3D => {
|
||||
rval.set(Int32Value(uniform_get(triple, WebGLCommand::GetUniformInt)))
|
||||
},
|
||||
constants::INT_VEC2 => unsafe {
|
||||
|
@ -5122,6 +5162,22 @@ impl TexPixels {
|
|||
pub(crate) fn size(&self) -> Size2D<u32> {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub(crate) fn pixel_format(&self) -> Option<PixelFormat> {
|
||||
self.pixel_format
|
||||
}
|
||||
|
||||
pub(crate) fn alpha_treatment(&self) -> Option<AlphaTreatment> {
|
||||
self.alpha_treatment
|
||||
}
|
||||
|
||||
pub(crate) fn y_axis_treatment(&self) -> YAxisTreatment {
|
||||
self.y_axis_treatment
|
||||
}
|
||||
|
||||
pub(crate) fn into_shared_memory(self) -> IpcSharedMemory {
|
||||
self.data
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum TexSource {
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::cmp;
|
|||
|
||||
use canvas_traits::webgl::{
|
||||
TexDataType, TexFormat, TexParameter, TexParameterBool, TexParameterInt, WebGLCommand,
|
||||
WebGLError, WebGLResult, WebGLTextureId, webgl_channel,
|
||||
WebGLError, WebGLResult, WebGLTextureId, WebGLVersion, webgl_channel,
|
||||
};
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
|
@ -158,7 +158,7 @@ impl WebGLTexture {
|
|||
} else {
|
||||
// This is the first time binding
|
||||
let face_count = match target {
|
||||
constants::TEXTURE_2D => 1,
|
||||
constants::TEXTURE_2D | constants::TEXTURE_2D_ARRAY | constants::TEXTURE_3D => 1,
|
||||
constants::TEXTURE_CUBE_MAP => 6,
|
||||
_ => return Err(WebGLError::InvalidEnum),
|
||||
};
|
||||
|
@ -314,16 +314,60 @@ impl WebGLTexture {
|
|||
TexParameterValue::Bool(_) => unreachable!("no settable tex params should be booleans"),
|
||||
};
|
||||
|
||||
let context = self.upcast::<WebGLObject>().context();
|
||||
let is_webgl2 = context.webgl_version() == WebGLVersion::WebGL2;
|
||||
|
||||
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));
|
||||
context.send_command(WebGLCommand::TexParameteri(target, param, int_value));
|
||||
Ok(())
|
||||
};
|
||||
if is_webgl2 {
|
||||
match param {
|
||||
constants::TEXTURE_BASE_LEVEL | constants::TEXTURE_MAX_LEVEL => {
|
||||
context.send_command(WebGLCommand::TexParameteri(target, param, int_value));
|
||||
return Ok(());
|
||||
},
|
||||
constants::TEXTURE_COMPARE_FUNC => match int_value as u32 {
|
||||
constants::LEQUAL |
|
||||
constants::GEQUAL |
|
||||
constants::LESS |
|
||||
constants::GREATER |
|
||||
constants::EQUAL |
|
||||
constants::NOTEQUAL |
|
||||
constants::ALWAYS |
|
||||
constants::NEVER => {
|
||||
context.send_command(WebGLCommand::TexParameteri(target, param, int_value));
|
||||
return Ok(());
|
||||
},
|
||||
_ => return Err(WebGLError::InvalidEnum),
|
||||
},
|
||||
constants::TEXTURE_COMPARE_MODE => match int_value as u32 {
|
||||
constants::COMPARE_REF_TO_TEXTURE | constants::NONE => {
|
||||
context.send_command(WebGLCommand::TexParameteri(target, param, int_value));
|
||||
return Ok(());
|
||||
},
|
||||
_ => return Err(WebGLError::InvalidEnum),
|
||||
},
|
||||
constants::TEXTURE_MAX_LOD | constants::TEXTURE_MIN_LOD => {
|
||||
context.send_command(WebGLCommand::TexParameterf(target, param, float_value));
|
||||
return Ok(());
|
||||
},
|
||||
constants::TEXTURE_WRAP_R => match int_value as u32 {
|
||||
constants::CLAMP_TO_EDGE | constants::MIRRORED_REPEAT | constants::REPEAT => {
|
||||
self.upcast::<WebGLObject>()
|
||||
.context()
|
||||
.send_command(WebGLCommand::TexParameteri(target, param, int_value));
|
||||
return Ok(());
|
||||
},
|
||||
_ => return Err(WebGLError::InvalidEnum),
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
match param {
|
||||
constants::TEXTURE_MIN_FILTER => match int_value as u32 {
|
||||
constants::NEAREST |
|
||||
|
@ -340,9 +384,7 @@ impl WebGLTexture {
|
|||
},
|
||||
constants::TEXTURE_WRAP_S | constants::TEXTURE_WRAP_T => match int_value as u32 {
|
||||
constants::CLAMP_TO_EDGE | constants::MIRRORED_REPEAT | constants::REPEAT => {
|
||||
self.upcast::<WebGLObject>()
|
||||
.context()
|
||||
.send_command(WebGLCommand::TexParameteri(target, param, int_value));
|
||||
context.send_command(WebGLCommand::TexParameteri(target, param, int_value));
|
||||
Ok(())
|
||||
},
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
|
@ -352,9 +394,7 @@ impl WebGLTexture {
|
|||
if float_value < 1. || !float_value.is_normal() {
|
||||
return Err(WebGLError::InvalidValue);
|
||||
}
|
||||
self.upcast::<WebGLObject>()
|
||||
.context()
|
||||
.send_command(WebGLCommand::TexParameterf(target, param, float_value));
|
||||
context.send_command(WebGLCommand::TexParameterf(target, param, float_value));
|
||||
Ok(())
|
||||
},
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue