mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Auto merge of #16893 - MortimerGoro:webgl_extensions, r=emilio
Implement WebGL extensions <!-- Please describe your changes on the following line: --> This PR provides the base for implementing WebGL extensions. It comes with the following ones already implemented and passing all related WebGL conformance tests: - OES_texture_float - OES_texture_float_linear - OES_texture_half_float - OES_texture_half_float_linear - OES_vertex_array_object I'll submit other extensions like compressed textures in a separate PR to ease the review process. I included the 5 extensions in this PR because it's easier to show/review how the WebGL extension base works. To pass all OES_texture_float_xxx tests I had to add some missing format conversions in WebGLRenderingContext.rs --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- 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/16893) <!-- Reviewable:end -->
This commit is contained in:
commit
b0976566fb
40 changed files with 1346 additions and 86 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -1116,6 +1116,11 @@ dependencies = [
|
|||
"libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "harfbuzz-sys"
|
||||
version = "0.1.7"
|
||||
|
@ -2323,6 +2328,8 @@ dependencies = [
|
|||
"euclid 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3511,6 +3518,7 @@ dependencies = [
|
|||
"checksum gleam 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86944a6a4d7f54507f8ee930192d971f18a7b1da526ff529b7a0d4043935380"
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum glx 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b280007fa9c7442cfd1e0b1addb8d1a59240267110e8705f8f7e2c7bfb7e2f72"
|
||||
"checksum half 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63d68db75012a85555434ee079e7e6337931f87a087ab2988becbadf64673a7f"
|
||||
"checksum harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6b76113246f5c089dcf272cf89c3f61168a4d77b50ec5b2c1fab8c628c9ea762"
|
||||
"checksum heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "556cd479866cf85c3f671209c85e8a6990211c916d1002c2fcb2e9b7cf60bc36"
|
||||
"checksum heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "46f96d52fb1564059fc97b85ef6165728cc30198ab60073bf114c66c4c89bb5d"
|
||||
|
|
|
@ -43,7 +43,9 @@ domobject_derive = {path = "../domobject_derive"}
|
|||
encoding = "0.2"
|
||||
euclid = "0.11"
|
||||
fnv = "1.0"
|
||||
gleam = "0.4"
|
||||
gfx_traits = {path = "../gfx_traits"}
|
||||
half = "1.0"
|
||||
heapsize = "0.3.6"
|
||||
heapsize_derive = "0.1"
|
||||
html5ever = {version = "0.16", features = ["heap_size", "unstable"]}
|
||||
|
|
|
@ -107,7 +107,7 @@ use style::viewport::ViewportRule;
|
|||
use time::Duration;
|
||||
use uuid::Uuid;
|
||||
use webrender_traits::{WebGLBufferId, WebGLError, WebGLFramebufferId, WebGLProgramId};
|
||||
use webrender_traits::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId};
|
||||
use webrender_traits::{WebGLRenderbufferId, WebGLShaderId, WebGLTextureId, WebGLVertexArrayId};
|
||||
use webvr_traits::WebVRGamepadHand;
|
||||
|
||||
/// A trait to allow tracing (only) DOM objects.
|
||||
|
@ -388,6 +388,7 @@ unsafe_no_jsmanaged_fields!(WebGLProgramId);
|
|||
unsafe_no_jsmanaged_fields!(WebGLRenderbufferId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLShaderId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLTextureId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLVertexArrayId);
|
||||
unsafe_no_jsmanaged_fields!(MediaList);
|
||||
unsafe_no_jsmanaged_fields!(WebVRGamepadHand);
|
||||
|
||||
|
|
|
@ -451,6 +451,8 @@ pub mod vrfieldofview;
|
|||
pub mod vrframedata;
|
||||
pub mod vrpose;
|
||||
pub mod vrstageparameters;
|
||||
pub mod webgl_extensions;
|
||||
pub use self::webgl_extensions::ext::*;
|
||||
pub mod webgl_validations;
|
||||
pub mod webglactiveinfo;
|
||||
pub mod webglbuffer;
|
||||
|
|
13
components/script/dom/webgl_extensions/ext/mod.rs
Normal file
13
components/script/dom/webgl_extensions/ext/mod.rs
Normal file
|
@ -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/. */
|
||||
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use super::{ext_constants, WebGLExtension, WebGLExtensions};
|
||||
|
||||
pub mod oestexturefloat;
|
||||
pub mod oestexturefloatlinear;
|
||||
pub mod oestexturehalffloat;
|
||||
pub mod oestexturehalffloatlinear;
|
||||
pub mod oesvertexarrayobject;
|
||||
pub mod webglvertexarrayobjectoes;
|
|
@ -0,0 +1,56 @@
|
|||
/* 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::OESTextureFloatBinding;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use dom_struct::dom_struct;
|
||||
use super::{constants as webgl, ext_constants as gl, WebGLExtension, WebGLExtensions};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OESTextureFloat {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl OESTextureFloat {
|
||||
fn new_inherited() -> OESTextureFloat {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExtension for OESTextureFloat {
|
||||
type Extension = OESTextureFloat;
|
||||
fn new(ctx: &WebGLRenderingContext) -> Root<OESTextureFloat> {
|
||||
reflect_dom_object(box OESTextureFloat::new_inherited(),
|
||||
&*ctx.global(),
|
||||
OESTextureFloatBinding::Wrap)
|
||||
}
|
||||
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool {
|
||||
ext.supports_any_gl_extension(&["GL_OES_texture_float",
|
||||
"GL_ARB_texture_float"])
|
||||
}
|
||||
|
||||
fn enable(ext: &WebGLExtensions) {
|
||||
// Enable FLOAT text data type
|
||||
ext.enable_tex_type(webgl::FLOAT);
|
||||
let needs_replace = !ext.supports_gl_extension("GL_OES_texture_float");
|
||||
if needs_replace {
|
||||
// Special internal formats must be used to avoid clamped float values
|
||||
ext.add_effective_tex_internal_format(webgl::RGBA, webgl::FLOAT, gl::RGBA32F);
|
||||
ext.add_effective_tex_internal_format(webgl::RGB, webgl::FLOAT, gl::RGB32F);
|
||||
ext.add_effective_tex_internal_format(webgl::LUMINANCE, webgl::FLOAT, gl::LUMINANCE32F_ARB);
|
||||
ext.add_effective_tex_internal_format(webgl::ALPHA, webgl::FLOAT, gl::ALPHA32F_ARB);
|
||||
ext.add_effective_tex_internal_format(webgl::LUMINANCE_ALPHA, webgl::FLOAT,
|
||||
gl::LUMINANCE_ALPHA32F_ARB);
|
||||
}
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"OES_texture_float"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* 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::OESTextureFloatLinearBinding;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use dom_struct::dom_struct;
|
||||
use super::{constants as webgl, WebGLExtension, WebGLExtensions};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OESTextureFloatLinear {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl OESTextureFloatLinear {
|
||||
fn new_inherited() -> OESTextureFloatLinear {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExtension for OESTextureFloatLinear {
|
||||
type Extension = OESTextureFloatLinear;
|
||||
fn new(ctx: &WebGLRenderingContext) -> Root<OESTextureFloatLinear> {
|
||||
reflect_dom_object(box OESTextureFloatLinear::new_inherited(),
|
||||
&*ctx.global(),
|
||||
OESTextureFloatLinearBinding::Wrap)
|
||||
}
|
||||
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool {
|
||||
ext.supports_any_gl_extension(&["GL_OES_texture_float_linear",
|
||||
"GL_ARB_texture_float"])
|
||||
}
|
||||
|
||||
fn enable(ext: &WebGLExtensions) {
|
||||
ext.enable_filterable_tex_type(webgl::FLOAT);
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"OES_texture_float_linear"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* 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::OESTextureHalfFloatBinding::{self, OESTextureHalfFloatConstants};
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use dom_struct::dom_struct;
|
||||
use super::{constants as webgl, ext_constants as gl, WebGLExtension, WebGLExtensions};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OESTextureHalfFloat {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl OESTextureHalfFloat {
|
||||
fn new_inherited() -> OESTextureHalfFloat {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExtension for OESTextureHalfFloat {
|
||||
type Extension = OESTextureHalfFloat;
|
||||
fn new(ctx: &WebGLRenderingContext) -> Root<OESTextureHalfFloat> {
|
||||
reflect_dom_object(box OESTextureHalfFloat::new_inherited(),
|
||||
&*ctx.global(),
|
||||
OESTextureHalfFloatBinding::Wrap)
|
||||
}
|
||||
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool {
|
||||
ext.supports_any_gl_extension(&["GL_OES_texture_half_float",
|
||||
"GL_ARB_half_float_pixel",
|
||||
"GL_NV_half_float"])
|
||||
}
|
||||
|
||||
fn enable(ext: &WebGLExtensions) {
|
||||
// Enable FLOAT text data type
|
||||
let hf = OESTextureHalfFloatConstants::HALF_FLOAT_OES;
|
||||
ext.enable_tex_type(hf);
|
||||
let needs_replace = !ext.supports_gl_extension("GL_OES_texture_float");
|
||||
if needs_replace {
|
||||
// Special internal formats must be used to avoid clamped float values
|
||||
ext.add_effective_tex_internal_format(webgl::RGBA, hf, gl::RGBA16F);
|
||||
ext.add_effective_tex_internal_format(webgl::RGB, hf, gl::RGB16F);
|
||||
ext.add_effective_tex_internal_format(webgl::LUMINANCE, hf, gl::LUMINANCE16F_ARB);
|
||||
ext.add_effective_tex_internal_format(webgl::ALPHA, hf, gl::ALPHA16F_ARB);
|
||||
ext.add_effective_tex_internal_format(webgl::LUMINANCE_ALPHA, hf, gl::LUMINANCE_ALPHA16F_ARB);
|
||||
}
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"OES_texture_half_float"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/* 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::OESTextureHalfFloatBinding::OESTextureHalfFloatConstants;
|
||||
use dom::bindings::codegen::Bindings::OESTextureHalfFloatLinearBinding;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use dom_struct::dom_struct;
|
||||
use super::{WebGLExtension, WebGLExtensions};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OESTextureHalfFloatLinear {
|
||||
reflector_: Reflector,
|
||||
}
|
||||
|
||||
impl OESTextureHalfFloatLinear {
|
||||
fn new_inherited() -> OESTextureHalfFloatLinear {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExtension for OESTextureHalfFloatLinear {
|
||||
type Extension = OESTextureHalfFloatLinear;
|
||||
fn new(ctx: &WebGLRenderingContext) -> Root<OESTextureHalfFloatLinear> {
|
||||
reflect_dom_object(box OESTextureHalfFloatLinear::new_inherited(),
|
||||
&*ctx.global(),
|
||||
OESTextureHalfFloatLinearBinding::Wrap)
|
||||
}
|
||||
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool {
|
||||
ext.supports_any_gl_extension(&["GL_OES_texture_float_linear",
|
||||
"GL_ARB_half_float_pixel",
|
||||
"GL_NV_half_float"])
|
||||
}
|
||||
|
||||
fn enable(ext: &WebGLExtensions) {
|
||||
ext.enable_filterable_tex_type(OESTextureHalfFloatConstants::HALF_FLOAT_OES);
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"OES_texture_half_float_linear"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/* 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::CanvasMsg;
|
||||
use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::{self, OESVertexArrayObjectMethods};
|
||||
use dom::bindings::codegen::Bindings::OESVertexArrayObjectBinding::OESVertexArrayObjectConstants;
|
||||
use dom::bindings::js::{JS, MutNullableJS, Root};
|
||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use dom::webglvertexarrayobjectoes::WebGLVertexArrayObjectOES;
|
||||
use dom_struct::dom_struct;
|
||||
use js::conversions::ToJSValConvertible;
|
||||
use js::jsapi::JSContext;
|
||||
use js::jsval::{JSVal, NullValue};
|
||||
use std::iter;
|
||||
use super::{WebGLExtension, WebGLExtensions};
|
||||
use webrender_traits::{self, WebGLCommand, WebGLError};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct OESVertexArrayObject {
|
||||
reflector_: Reflector,
|
||||
ctx: JS<WebGLRenderingContext>,
|
||||
bound_vao: MutNullableJS<WebGLVertexArrayObjectOES>,
|
||||
}
|
||||
|
||||
impl OESVertexArrayObject {
|
||||
fn new_inherited(ctx: &WebGLRenderingContext) -> OESVertexArrayObject {
|
||||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
ctx: JS::from_ref(ctx),
|
||||
bound_vao: MutNullableJS::new(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn get_current_binding(&self, cx:*mut JSContext) -> JSVal {
|
||||
rooted!(in(cx) let mut rval = NullValue());
|
||||
if let Some(bound_vao) = self.bound_vao.get() {
|
||||
unsafe {
|
||||
bound_vao.to_jsval(cx, rval.handle_mut());
|
||||
}
|
||||
}
|
||||
rval.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl OESVertexArrayObjectMethods for OESVertexArrayObject {
|
||||
// https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
|
||||
fn CreateVertexArrayOES(&self) -> Option<Root<WebGLVertexArrayObjectOES>> {
|
||||
let (sender, receiver) = webrender_traits::channel::msg_channel().unwrap();
|
||||
self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::CreateVertexArray(sender)));
|
||||
|
||||
let result = receiver.recv().unwrap();
|
||||
result.map(|vao_id| WebGLVertexArrayObjectOES::new(&self.global(), vao_id))
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
|
||||
fn DeleteVertexArrayOES(&self, vao: Option<&WebGLVertexArrayObjectOES>) {
|
||||
if let Some(vao) = vao {
|
||||
if vao.is_deleted() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Unbind deleted VAO if currently bound
|
||||
if let Some(bound_vao) = self.bound_vao.get() {
|
||||
if bound_vao.id() == vao.id() {
|
||||
self.bound_vao.set(None);
|
||||
self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(None)));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove VAO references from buffers
|
||||
let buffers = vao.bound_attrib_buffers();
|
||||
for buffer in buffers {
|
||||
buffer.remove_vao_reference(vao.id());
|
||||
}
|
||||
if let Some(buffer) = vao.bound_buffer_element_array() {
|
||||
buffer.remove_vao_reference(vao.id());
|
||||
}
|
||||
|
||||
// Delete the vao
|
||||
self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::DeleteVertexArray(vao.id())));
|
||||
vao.set_deleted();
|
||||
}
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
|
||||
fn IsVertexArrayOES(&self, vao: Option<&WebGLVertexArrayObjectOES>) -> bool {
|
||||
// Conformance tests expect false if vao never bound
|
||||
vao.map_or(false, |vao| !vao.is_deleted() && vao.ever_bound())
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
|
||||
fn BindVertexArrayOES(&self, vao: Option<&WebGLVertexArrayObjectOES>) {
|
||||
if let Some(bound_vao) = self.bound_vao.get() {
|
||||
// Store buffers attached to attrib pointers
|
||||
let buffers = self.ctx.borrow_bound_attrib_buffers();
|
||||
bound_vao.set_bound_attrib_buffers(buffers.iter().map(|(key, buffer)| {
|
||||
(*buffer).add_vao_reference(bound_vao.id());
|
||||
(*key, &**buffer)
|
||||
}));
|
||||
// Store element array buffer
|
||||
let element_array = self.ctx.bound_buffer_element_array();
|
||||
bound_vao.set_bound_buffer_element_array(element_array.as_ref().map(|buffer| {
|
||||
buffer.add_vao_reference(bound_vao.id());
|
||||
&**buffer
|
||||
}));
|
||||
}
|
||||
|
||||
if let Some(vao) = vao {
|
||||
if vao.is_deleted() {
|
||||
self.ctx.webgl_error(WebGLError::InvalidOperation);
|
||||
return;
|
||||
}
|
||||
|
||||
self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(Some(vao.id()))));
|
||||
vao.set_ever_bound();
|
||||
self.bound_vao.set(Some(&vao));
|
||||
|
||||
// Restore WebGLRenderingContext current bindings
|
||||
let buffers = vao.borrow_bound_attrib_buffers();
|
||||
self.ctx.set_bound_attrib_buffers(buffers.iter().map(|(k, v)| (*k, &**v)));
|
||||
let element_array = vao.bound_buffer_element_array();
|
||||
self.ctx.set_bound_buffer_element_array(element_array.as_ref().map(|buffer| &**buffer));
|
||||
} else {
|
||||
self.ctx.send_renderer_message(CanvasMsg::WebGL(WebGLCommand::BindVertexArray(None)));
|
||||
self.bound_vao.set(None);
|
||||
self.ctx.set_bound_attrib_buffers(iter::empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebGLExtension for OESVertexArrayObject {
|
||||
type Extension = OESVertexArrayObject;
|
||||
fn new(ctx: &WebGLRenderingContext) -> Root<OESVertexArrayObject> {
|
||||
reflect_dom_object(box OESVertexArrayObject::new_inherited(ctx),
|
||||
&*ctx.global(),
|
||||
OESVertexArrayObjectBinding::Wrap)
|
||||
}
|
||||
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool {
|
||||
ext.supports_any_gl_extension(&["GL_OES_vertex_array_object",
|
||||
"GL_ARB_vertex_array_object",
|
||||
"GL_APPLE_vertex_array_object"])
|
||||
}
|
||||
|
||||
fn enable(ext: &WebGLExtensions) {
|
||||
let query = OESVertexArrayObjectConstants::VERTEX_ARRAY_BINDING_OES;
|
||||
ext.add_query_parameter_handler(query, Box::new(|cx, webgl_ctx| {
|
||||
match webgl_ctx.get_extension_manager().get_dom_object::<OESVertexArrayObject>() {
|
||||
Some(dom_object) => {
|
||||
Ok(dom_object.get_current_binding(cx))
|
||||
},
|
||||
None => {
|
||||
// Extension instance not found!
|
||||
Err(WebGLError::InvalidOperation)
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
fn name() -> &'static str {
|
||||
"OES_vertex_array_object"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/* 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 core::cell::Ref;
|
||||
use core::iter::FromIterator;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::WebGLVertexArrayObjectOESBinding;
|
||||
use dom::bindings::js::{JS, MutNullableJS};
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
use dom::globalscope::GlobalScope;
|
||||
use dom::webglbuffer::WebGLBuffer;
|
||||
use dom::webglobject::WebGLObject;
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use webrender_traits::WebGLVertexArrayId;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct WebGLVertexArrayObjectOES {
|
||||
webgl_object_: WebGLObject,
|
||||
id: WebGLVertexArrayId,
|
||||
ever_bound: Cell<bool>,
|
||||
is_deleted: Cell<bool>,
|
||||
bound_attrib_buffers: DOMRefCell<HashMap<u32, JS<WebGLBuffer>>>,
|
||||
bound_buffer_element_array: MutNullableJS<WebGLBuffer>,
|
||||
}
|
||||
|
||||
impl WebGLVertexArrayObjectOES {
|
||||
fn new_inherited(id: WebGLVertexArrayId) -> WebGLVertexArrayObjectOES {
|
||||
Self {
|
||||
webgl_object_: WebGLObject::new_inherited(),
|
||||
id: id,
|
||||
ever_bound: Cell::new(false),
|
||||
is_deleted: Cell::new(false),
|
||||
bound_attrib_buffers: DOMRefCell::new(HashMap::new()),
|
||||
bound_buffer_element_array: MutNullableJS::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(global: &GlobalScope, id: WebGLVertexArrayId) -> Root<WebGLVertexArrayObjectOES> {
|
||||
reflect_dom_object(box WebGLVertexArrayObjectOES::new_inherited(id),
|
||||
global,
|
||||
WebGLVertexArrayObjectOESBinding::Wrap)
|
||||
}
|
||||
|
||||
pub fn id(&self) -> WebGLVertexArrayId {
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn is_deleted(&self) -> bool {
|
||||
self.is_deleted.get()
|
||||
}
|
||||
|
||||
pub fn set_deleted(&self) {
|
||||
self.is_deleted.set(true)
|
||||
}
|
||||
|
||||
pub fn ever_bound(&self) -> bool {
|
||||
return self.ever_bound.get()
|
||||
}
|
||||
|
||||
pub fn set_ever_bound(&self) {
|
||||
self.ever_bound.set(true);
|
||||
}
|
||||
|
||||
pub fn borrow_bound_attrib_buffers(&self) -> Ref<HashMap<u32, JS<WebGLBuffer>>> {
|
||||
self.bound_attrib_buffers.borrow()
|
||||
}
|
||||
|
||||
pub fn bound_attrib_buffers(&self) -> Vec<Root<WebGLBuffer>> {
|
||||
self.bound_attrib_buffers.borrow().iter().map(|(_, b)| Root::from_ref(&**b)).collect()
|
||||
}
|
||||
|
||||
pub fn set_bound_attrib_buffers<'a, T>(&self, iter: T) where T: Iterator<Item=(u32, &'a WebGLBuffer)> {
|
||||
*self.bound_attrib_buffers.borrow_mut() = HashMap::from_iter(iter.map(|(k,v)| (k, JS::from_ref(v))));
|
||||
}
|
||||
|
||||
pub fn bound_buffer_element_array(&self) -> Option<Root<WebGLBuffer>> {
|
||||
self.bound_buffer_element_array.get()
|
||||
}
|
||||
|
||||
pub fn set_bound_buffer_element_array(&self, buffer: Option<&WebGLBuffer>) {
|
||||
self.bound_buffer_element_array.set(buffer);
|
||||
}
|
||||
}
|
26
components/script/dom/webgl_extensions/extension.rs
Normal file
26
components/script/dom/webgl_extensions/extension.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* 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::bindings::reflector::DomObject;
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use super::WebGLExtensions;
|
||||
|
||||
/// Trait implemented by WebGL extensions.
|
||||
pub trait WebGLExtension: Sized where Self::Extension: DomObject + JSTraceable {
|
||||
type Extension;
|
||||
|
||||
/// Creates the DOM object of the WebGL extension.
|
||||
fn new(ctx: &WebGLRenderingContext) -> Root<Self::Extension>;
|
||||
|
||||
/// Checks if the extension is supported.
|
||||
fn is_supported(ext: &WebGLExtensions) -> bool;
|
||||
|
||||
/// Enable the extension.
|
||||
fn enable(ext: &WebGLExtensions);
|
||||
|
||||
/// Name of the WebGL Extension.
|
||||
fn name() -> &'static str;
|
||||
}
|
197
components/script/dom/webgl_extensions/extensions.rs
Normal file
197
components/script/dom/webgl_extensions/extensions.rs
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* 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 core::iter::FromIterator;
|
||||
use core::nonzero::NonZero;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::OESTextureHalfFloatBinding::OESTextureHalfFloatConstants;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use gleam::gl::GLenum;
|
||||
use heapsize::HeapSizeOf;
|
||||
use js::jsapi::{JSContext, JSObject};
|
||||
use js::jsval::JSVal;
|
||||
use ref_filter_map::ref_filter_map;
|
||||
use std::cell::Ref;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use super::{ext, WebGLExtension};
|
||||
use super::wrapper::{WebGLExtensionWrapper, TypedWebGLExtensionWrapper};
|
||||
use webrender_traits::WebGLError;
|
||||
|
||||
// Data types that are implemented for texImage2D and texSubImage2D in WebGLRenderingContext
|
||||
// but must trigger a InvalidValue error until the related WebGL Extensions are enabled.
|
||||
// Example: https://www.khronos.org/registry/webgl/extensions/OES_texture_float/
|
||||
const DEFAULT_DISABLED_TEX_TYPES: [GLenum; 2] = [
|
||||
constants::FLOAT, OESTextureHalfFloatConstants::HALF_FLOAT_OES
|
||||
];
|
||||
|
||||
// Data types that are implemented for textures in WebGLRenderingContext
|
||||
// but not allowed to use with linear filtering until the related WebGL Extensions are enabled.
|
||||
// Example: https://www.khronos.org/registry/webgl/extensions/OES_texture_float_linear/
|
||||
const DEFAULT_NOT_FILTERABLE_TEX_TYPES: [GLenum; 2] = [
|
||||
constants::FLOAT, OESTextureHalfFloatConstants::HALF_FLOAT_OES
|
||||
];
|
||||
|
||||
/// WebGL features that are enabled/disabled by WebGL Extensions.
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
struct WebGLExtensionFeatures {
|
||||
gl_extensions: HashSet<String>,
|
||||
disabled_tex_types: HashSet<GLenum>,
|
||||
not_filterable_tex_types: HashSet<GLenum>,
|
||||
effective_tex_internal_formats: HashMap<TexFormatType, u32>,
|
||||
query_parameter_handlers: HashMap<GLenum, WebGLQueryParameterHandler>
|
||||
}
|
||||
|
||||
impl Default for WebGLExtensionFeatures {
|
||||
fn default() -> WebGLExtensionFeatures {
|
||||
WebGLExtensionFeatures {
|
||||
gl_extensions: HashSet::new(),
|
||||
disabled_tex_types: DEFAULT_DISABLED_TEX_TYPES.iter().cloned().collect(),
|
||||
not_filterable_tex_types: DEFAULT_NOT_FILTERABLE_TEX_TYPES.iter().cloned().collect(),
|
||||
effective_tex_internal_formats: HashMap::new(),
|
||||
query_parameter_handlers: HashMap::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles the list of implemented, supported and enabled WebGL extensions.
|
||||
#[must_root]
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
pub struct WebGLExtensions {
|
||||
extensions: DOMRefCell<HashMap<String, Box<WebGLExtensionWrapper>>>,
|
||||
features: DOMRefCell<WebGLExtensionFeatures>,
|
||||
}
|
||||
|
||||
impl WebGLExtensions {
|
||||
pub fn new() -> WebGLExtensions {
|
||||
Self {
|
||||
extensions: DOMRefCell::new(HashMap::new()),
|
||||
features: DOMRefCell::new(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_once<F>(&self, cb: F) where F: FnOnce() -> String {
|
||||
if self.extensions.borrow().len() == 0 {
|
||||
let gl_str = cb();
|
||||
self.features.borrow_mut().gl_extensions = HashSet::from_iter(gl_str.split(&[',', ' '][..])
|
||||
.map(|s| s.into()));
|
||||
self.register_all_extensions();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register<T:'static + WebGLExtension + JSTraceable + HeapSizeOf>(&self) {
|
||||
let name = T::name().to_uppercase();
|
||||
self.extensions.borrow_mut().insert(name, box TypedWebGLExtensionWrapper::<T>::new());
|
||||
}
|
||||
|
||||
pub fn get_suported_extensions(&self) -> Vec<&'static str> {
|
||||
self.extensions.borrow().iter()
|
||||
.filter(|ref v| v.1.is_supported(&self))
|
||||
.map(|ref v| v.1.name())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn get_or_init_extension(&self, name: &str, ctx: &WebGLRenderingContext) -> Option<NonZero<*mut JSObject>> {
|
||||
let name = name.to_uppercase();
|
||||
self.extensions.borrow().get(&name).and_then(|extension| {
|
||||
if extension.is_supported(self) {
|
||||
Some(extension.instance_or_init(ctx, self))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_dom_object<T>(&self) -> Option<Root<T::Extension>>
|
||||
where T: 'static + WebGLExtension + JSTraceable + HeapSizeOf {
|
||||
let name = T::name().to_uppercase();
|
||||
self.extensions.borrow().get(&name).and_then(|extension| {
|
||||
extension.as_any().downcast_ref::<TypedWebGLExtensionWrapper<T>>().and_then(|extension| {
|
||||
extension.dom_object()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn supports_gl_extension(&self, name: &str) -> bool {
|
||||
self.features.borrow().gl_extensions.contains(name)
|
||||
}
|
||||
|
||||
pub fn supports_any_gl_extension(&self, names: &[&str]) -> bool {
|
||||
let features = self.features.borrow();
|
||||
names.iter().any(|name| features.gl_extensions.contains(*name))
|
||||
}
|
||||
|
||||
pub fn enable_tex_type(&self, data_type: GLenum) {
|
||||
self.features.borrow_mut().disabled_tex_types.remove(&data_type);
|
||||
}
|
||||
|
||||
pub fn is_tex_type_enabled(&self, data_type: GLenum) -> bool {
|
||||
self.features.borrow().disabled_tex_types.get(&data_type).is_none()
|
||||
}
|
||||
|
||||
pub fn add_effective_tex_internal_format(&self,
|
||||
source_internal_format: u32,
|
||||
source_data_type: u32,
|
||||
effective_internal_format: u32)
|
||||
{
|
||||
let format = TexFormatType(source_internal_format, source_data_type);
|
||||
self.features.borrow_mut().effective_tex_internal_formats.insert(format,
|
||||
effective_internal_format);
|
||||
|
||||
}
|
||||
|
||||
pub fn get_effective_tex_internal_format(&self,
|
||||
source_internal_format: u32,
|
||||
source_data_type: u32) -> u32 {
|
||||
let format = TexFormatType(source_internal_format, source_data_type);
|
||||
*(self.features.borrow().effective_tex_internal_formats.get(&format)
|
||||
.unwrap_or(&source_internal_format))
|
||||
}
|
||||
|
||||
pub fn enable_filterable_tex_type(&self, text_data_type: GLenum) {
|
||||
self.features.borrow_mut().not_filterable_tex_types.remove(&text_data_type);
|
||||
}
|
||||
|
||||
pub fn is_filterable(&self, text_data_type: u32) -> bool {
|
||||
self.features.borrow().not_filterable_tex_types.get(&text_data_type).is_none()
|
||||
}
|
||||
|
||||
pub fn add_query_parameter_handler(&self, name: GLenum, f: Box<WebGLQueryParameterFunc>) {
|
||||
let handler = WebGLQueryParameterHandler {
|
||||
func: f
|
||||
};
|
||||
self.features.borrow_mut().query_parameter_handlers.insert(name, handler);
|
||||
}
|
||||
|
||||
pub fn get_query_parameter_handler(&self, name: GLenum) -> Option<Ref<Box<WebGLQueryParameterFunc>>> {
|
||||
ref_filter_map(self.features.borrow(), |features| {
|
||||
features.query_parameter_handlers.get(&name).map(|item| &item.func)
|
||||
})
|
||||
}
|
||||
|
||||
fn register_all_extensions(&self) {
|
||||
self.register::<ext::oestexturefloat::OESTextureFloat>();
|
||||
self.register::<ext::oestexturefloatlinear::OESTextureFloatLinear>();
|
||||
self.register::<ext::oestexturehalffloat::OESTextureHalfFloat>();
|
||||
self.register::<ext::oestexturehalffloatlinear::OESTextureHalfFloatLinear>();
|
||||
self.register::<ext::oesvertexarrayobject::OESVertexArrayObject>();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper structs
|
||||
#[derive(JSTraceable, HeapSizeOf, PartialEq, Eq, Hash)]
|
||||
struct TexFormatType(u32, u32);
|
||||
|
||||
type WebGLQueryParameterFunc = Fn(*mut JSContext, &WebGLRenderingContext)
|
||||
-> Result<JSVal, WebGLError>;
|
||||
|
||||
#[derive(HeapSizeOf)]
|
||||
struct WebGLQueryParameterHandler {
|
||||
#[ignore_heap_size_of = "Closures are hard"]
|
||||
func: Box<WebGLQueryParameterFunc>
|
||||
}
|
||||
|
||||
unsafe_no_jsmanaged_fields!(WebGLQueryParameterHandler);
|
25
components/script/dom/webgl_extensions/mod.rs
Normal file
25
components/script/dom/webgl_extensions/mod.rs
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* 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 mod ext;
|
||||
mod extension;
|
||||
mod extensions;
|
||||
mod wrapper;
|
||||
|
||||
// Some extra constants not exposed in WebGLRenderingContext constants
|
||||
pub mod ext_constants {
|
||||
pub const ALPHA16F_ARB: u32 = 0x881C;
|
||||
pub const ALPHA32F_ARB: u32 = 0x8816;
|
||||
pub const LUMINANCE16F_ARB: u32 = 0x881E;
|
||||
pub const LUMINANCE32F_ARB: u32 = 0x8818;
|
||||
pub const LUMINANCE_ALPHA16F_ARB: u32 = 0x881F;
|
||||
pub const LUMINANCE_ALPHA32F_ARB: u32 = 0x8819;
|
||||
pub const RGBA16F: u32 = 0x881A;
|
||||
pub const RGB16F: u32 = 0x881B;
|
||||
pub const RGBA32F: u32 = 0x8814;
|
||||
pub const RGB32F: u32 = 0x8815;
|
||||
}
|
||||
|
||||
pub use self::extension::WebGLExtension;
|
||||
pub use self::extensions::WebGLExtensions;
|
85
components/script/dom/webgl_extensions/wrapper.rs
Normal file
85
components/script/dom/webgl_extensions/wrapper.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* 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 core::nonzero::NonZero;
|
||||
use dom::bindings::js::{MutNullableJS, Root};
|
||||
use dom::bindings::reflector::DomObject;
|
||||
use dom::bindings::trace::JSTraceable;
|
||||
use dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use heapsize::HeapSizeOf;
|
||||
use js::jsapi::JSObject;
|
||||
use std::any::Any;
|
||||
use super::{WebGLExtension, WebGLExtensions};
|
||||
|
||||
/// Trait used internally by WebGLExtensions to store and
|
||||
/// handle the different WebGL extensions in a common list.
|
||||
pub trait WebGLExtensionWrapper: JSTraceable + HeapSizeOf {
|
||||
fn instance_or_init(&self,
|
||||
ctx: &WebGLRenderingContext,
|
||||
ext: &WebGLExtensions)
|
||||
-> NonZero<*mut JSObject>;
|
||||
fn is_supported(&self, &WebGLExtensions) -> bool;
|
||||
fn enable(&self, ext: &WebGLExtensions);
|
||||
fn name(&self) -> &'static str;
|
||||
fn as_any(&self) -> &Any;
|
||||
}
|
||||
|
||||
#[must_root]
|
||||
#[derive(JSTraceable, HeapSizeOf)]
|
||||
pub struct TypedWebGLExtensionWrapper<T: WebGLExtension> {
|
||||
extension: MutNullableJS<T::Extension>
|
||||
}
|
||||
|
||||
/// Typed WebGL Extension implementation.
|
||||
/// Exposes the exact MutNullableJS<DOMObject> type defined by the extension.
|
||||
impl<T: WebGLExtension> TypedWebGLExtensionWrapper<T> {
|
||||
pub fn new() -> TypedWebGLExtensionWrapper<T> {
|
||||
TypedWebGLExtensionWrapper {
|
||||
extension: MutNullableJS::new(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WebGLExtensionWrapper for TypedWebGLExtensionWrapper<T>
|
||||
where T: WebGLExtension + JSTraceable + HeapSizeOf + 'static {
|
||||
#[allow(unsafe_code)]
|
||||
fn instance_or_init(&self,
|
||||
ctx: &WebGLRenderingContext,
|
||||
ext: &WebGLExtensions)
|
||||
-> NonZero<*mut JSObject> {
|
||||
let mut enabled = true;
|
||||
let extension = self.extension.or_init(|| {
|
||||
enabled = false;
|
||||
T::new(ctx)
|
||||
});
|
||||
if !enabled {
|
||||
self.enable(ext);
|
||||
}
|
||||
unsafe {
|
||||
NonZero::new(extension.reflector().get_jsobject().get())
|
||||
}
|
||||
}
|
||||
|
||||
fn is_supported(&self, ext: &WebGLExtensions) -> bool {
|
||||
self.extension.get().is_some() || T::is_supported(ext)
|
||||
}
|
||||
|
||||
fn enable(&self, ext: &WebGLExtensions) {
|
||||
T::enable(ext);
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
T::name()
|
||||
}
|
||||
|
||||
fn as_any<'a>(&'a self) -> &'a Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> TypedWebGLExtensionWrapper<T> where T: WebGLExtension + JSTraceable + HeapSizeOf + 'static {
|
||||
pub fn dom_object(&self) -> Option<Root<T::Extension>> {
|
||||
self.extension.get()
|
||||
}
|
||||
}
|
|
@ -2,24 +2,25 @@
|
|||
* 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::OESTextureHalfFloatBinding::OESTextureHalfFloatConstants;
|
||||
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, )+) => {
|
||||
($name: ident, $($variant:ident => $mod:ident::$constant:ident, )+) => {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, JSTraceable, HeapSizeOf)]
|
||||
#[repr(u32)]
|
||||
pub enum $name {
|
||||
$(
|
||||
$variant = constants::$constant,
|
||||
$variant = $mod::$constant,
|
||||
)+
|
||||
}
|
||||
|
||||
impl $name {
|
||||
pub fn from_gl_constant(constant: u32) -> Option<Self> {
|
||||
Some(match constant {
|
||||
$(constants::$constant => $name::$variant, )+
|
||||
$($mod::$constant => $name::$variant, )+
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
@ -33,13 +34,13 @@ macro_rules! type_safe_wrapper {
|
|||
}
|
||||
|
||||
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,
|
||||
Texture2D => constants::TEXTURE_2D,
|
||||
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,
|
||||
}
|
||||
|
||||
impl TexImageTarget {
|
||||
|
@ -52,10 +53,12 @@ impl TexImageTarget {
|
|||
}
|
||||
|
||||
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,
|
||||
UnsignedByte => constants::UNSIGNED_BYTE,
|
||||
UnsignedShort4444 => constants::UNSIGNED_SHORT_4_4_4_4,
|
||||
UnsignedShort5551 => constants::UNSIGNED_SHORT_5_5_5_1,
|
||||
UnsignedShort565 => constants::UNSIGNED_SHORT_5_6_5,
|
||||
Float => constants::FLOAT,
|
||||
HalfFloat => OESTextureHalfFloatConstants::HALF_FLOAT_OES,
|
||||
}
|
||||
|
||||
impl TexDataType {
|
||||
|
@ -67,6 +70,8 @@ impl TexDataType {
|
|||
UnsignedShort4444 |
|
||||
UnsignedShort5551 |
|
||||
UnsignedShort565 => 2,
|
||||
Float => 4,
|
||||
HalfFloat => 2,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,17 +84,19 @@ impl TexDataType {
|
|||
UnsignedShort565 => 3,
|
||||
UnsignedShort5551 => 4,
|
||||
UnsignedShort4444 => 4,
|
||||
Float => 1,
|
||||
HalfFloat => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type_safe_wrapper! { TexFormat,
|
||||
DepthComponent => DEPTH_COMPONENT,
|
||||
Alpha => ALPHA,
|
||||
RGB => RGB,
|
||||
RGBA => RGBA,
|
||||
Luminance => LUMINANCE,
|
||||
LuminanceAlpha => LUMINANCE_ALPHA,
|
||||
DepthComponent => constants::DEPTH_COMPONENT,
|
||||
Alpha => constants::ALPHA,
|
||||
RGB => constants::RGB,
|
||||
RGBA => constants::RGBA,
|
||||
Luminance => constants::LUMINANCE,
|
||||
LuminanceAlpha => constants::LUMINANCE_ALPHA,
|
||||
}
|
||||
|
||||
impl TexFormat {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
|
||||
use canvas_traits::CanvasMsg;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::WebGLBufferBinding;
|
||||
use dom::bindings::js::Root;
|
||||
use dom::bindings::reflector::reflect_dom_object;
|
||||
|
@ -12,8 +13,9 @@ use dom::window::Window;
|
|||
use dom_struct::dom_struct;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashSet;
|
||||
use webrender_traits;
|
||||
use webrender_traits::{WebGLBufferId, WebGLCommand, WebGLError, WebGLResult};
|
||||
use webrender_traits::{WebGLBufferId, WebGLCommand, WebGLError, WebGLResult, WebGLVertexArrayId};
|
||||
|
||||
#[dom_struct]
|
||||
pub struct WebGLBuffer {
|
||||
|
@ -23,6 +25,9 @@ pub struct WebGLBuffer {
|
|||
target: Cell<Option<u32>>,
|
||||
capacity: Cell<usize>,
|
||||
is_deleted: Cell<bool>,
|
||||
// The Vertex Array Objects that are referencing this buffer
|
||||
vao_references: DOMRefCell<Option<HashSet<WebGLVertexArrayId>>>,
|
||||
pending_delete: Cell<bool>,
|
||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||
renderer: IpcSender<CanvasMsg>,
|
||||
}
|
||||
|
@ -37,6 +42,8 @@ impl WebGLBuffer {
|
|||
target: Cell::new(None),
|
||||
capacity: Cell::new(0),
|
||||
is_deleted: Cell::new(false),
|
||||
vao_references: DOMRefCell::new(None),
|
||||
pending_delete: Cell::new(false),
|
||||
renderer: renderer,
|
||||
}
|
||||
}
|
||||
|
@ -112,6 +119,36 @@ impl WebGLBuffer {
|
|||
pub fn target(&self) -> Option<u32> {
|
||||
self.target.get()
|
||||
}
|
||||
|
||||
pub fn is_attached_to_vao(&self) -> bool {
|
||||
self.vao_references.borrow().as_ref().map_or(false, |vaos| !vaos.is_empty())
|
||||
}
|
||||
|
||||
pub fn set_pending_delete(&self) {
|
||||
self.pending_delete.set(true);
|
||||
}
|
||||
|
||||
pub fn add_vao_reference(&self, id: WebGLVertexArrayId) {
|
||||
let mut vao_refs = self.vao_references.borrow_mut();
|
||||
if let Some(ref mut vao_refs) = *vao_refs {
|
||||
vao_refs.insert(id);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut map = HashSet::new();
|
||||
map.insert(id);
|
||||
*vao_refs = Some(map);
|
||||
}
|
||||
|
||||
pub fn remove_vao_reference(&self, id: WebGLVertexArrayId) {
|
||||
if let Some(ref mut vao_refs) = *self.vao_references.borrow_mut() {
|
||||
if vao_refs.take(&id).is_some() && self.pending_delete.get() {
|
||||
// WebGL spec: The deleted buffers should no longer be valid when the VAOs are deleted
|
||||
let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteBuffer(self.id)));
|
||||
self.is_deleted.set(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WebGLBuffer {
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
|
||||
use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt};
|
||||
use canvas_traits::{CanvasCommonMsg, CanvasMsg, byte_swap, multiply_u8_pixel};
|
||||
use core::cell::Ref;
|
||||
use core::iter::FromIterator;
|
||||
use core::nonzero::NonZero;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes};
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||
|
@ -20,6 +23,7 @@ use dom::globalscope::GlobalScope;
|
|||
use dom::htmlcanvaselement::HTMLCanvasElement;
|
||||
use dom::htmlcanvaselement::utils as canvas_utils;
|
||||
use dom::node::{Node, NodeDamage, window_from_node};
|
||||
use dom::webgl_extensions::WebGLExtensions;
|
||||
use dom::webgl_validations::WebGLValidator;
|
||||
use dom::webgl_validations::tex_image_2d::{CommonTexImage2DValidator, CommonTexImage2DValidatorResult};
|
||||
use dom::webgl_validations::tex_image_2d::{TexImage2DValidator, TexImage2DValidatorResult};
|
||||
|
@ -37,6 +41,7 @@ use dom::webgluniformlocation::WebGLUniformLocation;
|
|||
use dom::window::Window;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::size::Size2D;
|
||||
use half::f16;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use js::conversions::ConversionBehavior;
|
||||
use js::jsapi::{JSContext, JSObject, Type, Rooted};
|
||||
|
@ -47,6 +52,7 @@ use net_traits::image_cache::ImageResponse;
|
|||
use offscreen_gl_context::{GLContextAttributes, GLLimits};
|
||||
use script_traits::ScriptMsg as ConstellationMsg;
|
||||
use std::cell::Cell;
|
||||
use std::collections::HashMap;
|
||||
use webrender_traits;
|
||||
use webrender_traits::{WebGLCommand, WebGLError, WebGLFramebufferBindingRequest, WebGLParameter};
|
||||
use webrender_traits::WebGLError::*;
|
||||
|
@ -143,6 +149,7 @@ pub struct WebGLRenderingContext {
|
|||
bound_texture_cube_map: MutNullableJS<WebGLTexture>,
|
||||
bound_buffer_array: MutNullableJS<WebGLBuffer>,
|
||||
bound_buffer_element_array: MutNullableJS<WebGLBuffer>,
|
||||
bound_attrib_buffers: DOMRefCell<HashMap<u32, JS<WebGLBuffer>>>,
|
||||
current_program: MutNullableJS<WebGLProgram>,
|
||||
#[ignore_heap_size_of = "Because it's small"]
|
||||
current_vertex_attrib_0: Cell<(f32, f32, f32, f32)>,
|
||||
|
@ -150,6 +157,7 @@ pub struct WebGLRenderingContext {
|
|||
current_scissor: Cell<(i32, i32, i32, i32)>,
|
||||
#[ignore_heap_size_of = "Because it's small"]
|
||||
current_clear_color: Cell<(f32, f32, f32, f32)>,
|
||||
extension_manager: WebGLExtensions
|
||||
}
|
||||
|
||||
impl WebGLRenderingContext {
|
||||
|
@ -178,11 +186,13 @@ impl WebGLRenderingContext {
|
|||
bound_texture_cube_map: MutNullableJS::new(None),
|
||||
bound_buffer_array: MutNullableJS::new(None),
|
||||
bound_buffer_element_array: MutNullableJS::new(None),
|
||||
bound_attrib_buffers: DOMRefCell::new(HashMap::new()),
|
||||
bound_renderbuffer: MutNullableJS::new(None),
|
||||
current_program: MutNullableJS::new(None),
|
||||
current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)),
|
||||
current_scissor: Cell::new((0, 0, size.width, size.height)),
|
||||
current_clear_color: Cell::new((0.0, 0.0, 0.0, 0.0))
|
||||
current_clear_color: Cell::new((0.0, 0.0, 0.0, 0.0)),
|
||||
extension_manager: WebGLExtensions::new()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -221,6 +231,22 @@ impl WebGLRenderingContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn borrow_bound_attrib_buffers(&self) -> Ref<HashMap<u32, JS<WebGLBuffer>>> {
|
||||
self.bound_attrib_buffers.borrow()
|
||||
}
|
||||
|
||||
pub fn set_bound_attrib_buffers<'a, T>(&self, iter: T) where T: Iterator<Item=(u32, &'a WebGLBuffer)> {
|
||||
*self.bound_attrib_buffers.borrow_mut() = HashMap::from_iter(iter.map(|(k,v)| (k, JS::from_ref(v))));
|
||||
}
|
||||
|
||||
pub fn bound_buffer_element_array(&self) -> Option<Root<WebGLBuffer>> {
|
||||
self.bound_buffer_element_array.get()
|
||||
}
|
||||
|
||||
pub fn set_bound_buffer_element_array(&self, buffer: Option<&WebGLBuffer>) {
|
||||
self.bound_buffer_element_array.set(buffer);
|
||||
}
|
||||
|
||||
pub fn recreate(&self, size: Size2D<i32>) {
|
||||
self.ipc_renderer.send(CanvasMsg::Common(CanvasCommonMsg::Recreate(size))).unwrap();
|
||||
|
||||
|
@ -245,6 +271,14 @@ impl WebGLRenderingContext {
|
|||
self.ipc_renderer.clone()
|
||||
}
|
||||
|
||||
pub fn send_renderer_message(&self, msg: CanvasMsg) {
|
||||
self.ipc_renderer.send(msg).unwrap();
|
||||
}
|
||||
|
||||
pub fn get_extension_manager<'a>(&'a self) -> &'a WebGLExtensions {
|
||||
&self.extension_manager
|
||||
}
|
||||
|
||||
pub fn webgl_error(&self, err: WebGLError) {
|
||||
// TODO(emilio): Add useful debug messages to this
|
||||
warn!("WebGL error: {:?}, previous error was {:?}", err, self.last_error.get());
|
||||
|
@ -296,6 +330,23 @@ impl WebGLRenderingContext {
|
|||
};
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -329,6 +380,37 @@ impl WebGLRenderingContext {
|
|||
}
|
||||
}
|
||||
|
||||
// LINEAR filtering may be forbidden when using WebGL extensions.
|
||||
// https://www.khronos.org/registry/webgl/extensions/OES_texture_float_linear/
|
||||
fn validate_filterable_texture(&self,
|
||||
texture: &WebGLTexture,
|
||||
target: TexImageTarget,
|
||||
level: u32,
|
||||
format: TexFormat,
|
||||
width: u32,
|
||||
height: u32,
|
||||
data_type: TexDataType)
|
||||
-> bool
|
||||
{
|
||||
if self.extension_manager.is_filterable(data_type.as_gl_constant()) || !texture.is_using_linear_filtering() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle validation failed: LINEAR filtering not valid for this texture
|
||||
// WebGL Conformance tests expect to fallback to [0, 0, 0, 255] RGBA UNSIGNED_BYTE
|
||||
let data_type = TexDataType::UnsignedByte;
|
||||
let expected_byte_length = width * height * 4;
|
||||
let mut pixels = vec![0u8; expected_byte_length as usize];
|
||||
for rgba8 in pixels.chunks_mut(4) {
|
||||
rgba8[3] = 255u8;
|
||||
}
|
||||
|
||||
let pixels = self.prepare_pixels(format, data_type, width, height, 1, true, true, pixels);
|
||||
self.tex_image_2d(texture, target, data_type, format, level, width, height, 0, 1, pixels);
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn validate_stencil_actions(&self, action: u32) -> bool {
|
||||
match action {
|
||||
0 | constants::KEEP | constants::REPLACE | constants::INCR | constants::DECR |
|
||||
|
@ -369,6 +451,14 @@ impl WebGLRenderingContext {
|
|||
true
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||
#[inline]
|
||||
fn luminance(r: u8, g: u8, b: u8) -> u8 {
|
||||
(0.2126 * (r as f32) +
|
||||
0.7152 * (g as f32) +
|
||||
0.0722 * (b as f32)) as u8
|
||||
}
|
||||
|
||||
/// Translates an image in rgba8 (red in the first byte) format to
|
||||
/// the format that was requested of TexImage.
|
||||
///
|
||||
|
@ -391,7 +481,6 @@ impl WebGLRenderingContext {
|
|||
(TexFormat::RGBA, TexDataType::UnsignedByte) => pixels,
|
||||
(TexFormat::RGB, TexDataType::UnsignedByte) => {
|
||||
// Remove alpha channel
|
||||
let pixel_count = pixels.len() / 4;
|
||||
let mut rgb8 = Vec::<u8>::with_capacity(pixel_count * 3);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
rgb8.push(rgba8[0]);
|
||||
|
@ -400,6 +489,32 @@ impl WebGLRenderingContext {
|
|||
}
|
||||
rgb8
|
||||
},
|
||||
|
||||
(TexFormat::Alpha, TexDataType::UnsignedByte) => {
|
||||
let mut alpha = Vec::<u8>::with_capacity(pixel_count);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
alpha.push(rgba8[3]);
|
||||
}
|
||||
alpha
|
||||
},
|
||||
|
||||
(TexFormat::Luminance, TexDataType::UnsignedByte) => {
|
||||
let mut luminance = Vec::<u8>::with_capacity(pixel_count);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
luminance.push(Self::luminance(rgba8[0], rgba8[1], rgba8[2]));
|
||||
}
|
||||
luminance
|
||||
},
|
||||
|
||||
(TexFormat::LuminanceAlpha, TexDataType::UnsignedByte) => {
|
||||
let mut data = Vec::<u8>::with_capacity(pixel_count * 2);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
data.push(Self::luminance(rgba8[0], rgba8[1], rgba8[2]));
|
||||
data.push(rgba8[3]);
|
||||
}
|
||||
data
|
||||
},
|
||||
|
||||
(TexFormat::RGBA, TexDataType::UnsignedShort4444) => {
|
||||
let mut rgba4 = Vec::<u8>::with_capacity(pixel_count * 2);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
|
@ -432,10 +547,107 @@ impl WebGLRenderingContext {
|
|||
rgb565
|
||||
}
|
||||
|
||||
|
||||
(TexFormat::RGBA, TexDataType::Float) => {
|
||||
let mut rgbaf32 = Vec::<u8>::with_capacity(pixel_count * 16);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
rgbaf32.write_f32::<NativeEndian>(rgba8[0] as f32).unwrap();
|
||||
rgbaf32.write_f32::<NativeEndian>(rgba8[1] as f32).unwrap();
|
||||
rgbaf32.write_f32::<NativeEndian>(rgba8[2] as f32).unwrap();
|
||||
rgbaf32.write_f32::<NativeEndian>(rgba8[3] as f32).unwrap();
|
||||
}
|
||||
rgbaf32
|
||||
}
|
||||
|
||||
(TexFormat::RGB, TexDataType::Float) => {
|
||||
let mut rgbf32 = Vec::<u8>::with_capacity(pixel_count * 12);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
rgbf32.write_f32::<NativeEndian>(rgba8[0] as f32).unwrap();
|
||||
rgbf32.write_f32::<NativeEndian>(rgba8[1] as f32).unwrap();
|
||||
rgbf32.write_f32::<NativeEndian>(rgba8[2] as f32).unwrap();
|
||||
}
|
||||
rgbf32
|
||||
}
|
||||
|
||||
(TexFormat::Alpha, TexDataType::Float) => {
|
||||
let mut alpha = Vec::<u8>::with_capacity(pixel_count * 4);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
alpha.write_f32::<NativeEndian>(rgba8[0] as f32).unwrap();
|
||||
}
|
||||
alpha
|
||||
},
|
||||
|
||||
(TexFormat::Luminance, TexDataType::Float) => {
|
||||
let mut luminance = Vec::<u8>::with_capacity(pixel_count * 4);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
let p = Self::luminance(rgba8[0], rgba8[1], rgba8[2]);
|
||||
luminance.write_f32::<NativeEndian>(p as f32).unwrap();
|
||||
}
|
||||
luminance
|
||||
},
|
||||
|
||||
(TexFormat::LuminanceAlpha, TexDataType::Float) => {
|
||||
let mut data = Vec::<u8>::with_capacity(pixel_count * 8);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
let p = Self::luminance(rgba8[0], rgba8[1], rgba8[2]);
|
||||
data.write_f32::<NativeEndian>(p as f32).unwrap();
|
||||
data.write_f32::<NativeEndian>(rgba8[3] as f32).unwrap();
|
||||
}
|
||||
data
|
||||
},
|
||||
|
||||
(TexFormat::RGBA, TexDataType::HalfFloat) => {
|
||||
let mut rgbaf16 = Vec::<u8>::with_capacity(pixel_count * 8);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
rgbaf16.write_u16::<NativeEndian>(f16::from_f32(rgba8[0] as f32).as_bits()).unwrap();
|
||||
rgbaf16.write_u16::<NativeEndian>(f16::from_f32(rgba8[1] as f32).as_bits()).unwrap();
|
||||
rgbaf16.write_u16::<NativeEndian>(f16::from_f32(rgba8[2] as f32).as_bits()).unwrap();
|
||||
rgbaf16.write_u16::<NativeEndian>(f16::from_f32(rgba8[3] as f32).as_bits()).unwrap();
|
||||
}
|
||||
rgbaf16
|
||||
},
|
||||
|
||||
(TexFormat::RGB, TexDataType::HalfFloat) => {
|
||||
let mut rgbf16 = Vec::<u8>::with_capacity(pixel_count * 6);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
rgbf16.write_u16::<NativeEndian>(f16::from_f32(rgba8[0] as f32).as_bits()).unwrap();
|
||||
rgbf16.write_u16::<NativeEndian>(f16::from_f32(rgba8[1] as f32).as_bits()).unwrap();
|
||||
rgbf16.write_u16::<NativeEndian>(f16::from_f32(rgba8[2] as f32).as_bits()).unwrap();
|
||||
}
|
||||
rgbf16
|
||||
},
|
||||
|
||||
(TexFormat::Alpha, TexDataType::HalfFloat) => {
|
||||
let mut alpha = Vec::<u8>::with_capacity(pixel_count * 2);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
alpha.write_u16::<NativeEndian>(f16::from_f32(rgba8[3] as f32).as_bits()).unwrap();
|
||||
}
|
||||
alpha
|
||||
},
|
||||
|
||||
(TexFormat::Luminance, TexDataType::HalfFloat) => {
|
||||
let mut luminance = Vec::<u8>::with_capacity(pixel_count * 4);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
let p = Self::luminance(rgba8[0], rgba8[1], rgba8[2]);
|
||||
luminance.write_u16::<NativeEndian>(f16::from_f32(p as f32).as_bits()).unwrap();
|
||||
}
|
||||
luminance
|
||||
},
|
||||
|
||||
(TexFormat::LuminanceAlpha, TexDataType::HalfFloat) => {
|
||||
let mut data = Vec::<u8>::with_capacity(pixel_count * 8);
|
||||
for rgba8 in pixels.chunks(4) {
|
||||
let p = Self::luminance(rgba8[0], rgba8[1], rgba8[2]);
|
||||
data.write_u16::<NativeEndian>(f16::from_f32(p as f32).as_bits()).unwrap();
|
||||
data.write_u16::<NativeEndian>(f16::from_f32(rgba8[3] as f32).as_bits()).unwrap();
|
||||
}
|
||||
data
|
||||
},
|
||||
|
||||
// Validation should have ensured that we only hit the
|
||||
// above cases, but we haven't turned the (format, type)
|
||||
// into an enum yet so there's a default case here.
|
||||
_ => unreachable!()
|
||||
_ => unreachable!("Unsupported formats {:?} {:?}", format, data_type)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -522,9 +734,11 @@ impl WebGLRenderingContext {
|
|||
// If it is UNSIGNED_BYTE, a Uint8Array must be supplied;
|
||||
// if it is UNSIGNED_SHORT_5_6_5, UNSIGNED_SHORT_4_4_4_4,
|
||||
// or UNSIGNED_SHORT_5_5_5_1, a Uint16Array must be supplied.
|
||||
// or FLOAT, a Float32Array must be supplied.
|
||||
// If the types do not match, an INVALID_OPERATION error is generated.
|
||||
typedarray!(in(cx) let typedarray_u8: Uint8Array = data);
|
||||
typedarray!(in(cx) let typedarray_u16: Uint16Array = data);
|
||||
typedarray!(in(cx) let typedarray_f32: Float32Array = data);
|
||||
let received_size = if data.is_null() {
|
||||
element_size
|
||||
} else {
|
||||
|
@ -532,6 +746,8 @@ impl WebGLRenderingContext {
|
|||
2
|
||||
} else if typedarray_u8.is_ok() {
|
||||
1
|
||||
} else if typedarray_f32.is_ok() {
|
||||
4
|
||||
} else {
|
||||
self.webgl_error(InvalidOperation);
|
||||
return Err(());
|
||||
|
@ -700,7 +916,7 @@ impl WebGLRenderingContext {
|
|||
}
|
||||
|
||||
fn tex_image_2d(&self,
|
||||
texture: Root<WebGLTexture>,
|
||||
texture: &WebGLTexture,
|
||||
target: TexImageTarget,
|
||||
data_type: TexDataType,
|
||||
internal_format: TexFormat,
|
||||
|
@ -728,12 +944,17 @@ impl WebGLRenderingContext {
|
|||
.send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(constants::UNPACK_ALIGNMENT, unpacking_alignment as i32)))
|
||||
.unwrap();
|
||||
|
||||
let format = internal_format.as_gl_constant();
|
||||
let data_type = data_type.as_gl_constant();
|
||||
let internal_format = self.extension_manager.get_effective_tex_internal_format(format, data_type);
|
||||
|
||||
// TODO(emilio): convert colorspace if requested
|
||||
let msg = WebGLCommand::TexImage2D(target.as_gl_constant(), level as i32,
|
||||
internal_format.as_gl_constant() as i32,
|
||||
internal_format as i32,
|
||||
width as i32, height as i32,
|
||||
internal_format.as_gl_constant(),
|
||||
data_type.as_gl_constant(), pixels);
|
||||
format,
|
||||
data_type,
|
||||
pixels);
|
||||
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(msg))
|
||||
|
@ -807,6 +1028,14 @@ impl WebGLRenderingContext {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn get_gl_extensions(&self) -> String {
|
||||
let (sender, receiver) = webrender_traits::channel::msg_channel().unwrap();
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::GetExtensions(sender)))
|
||||
.unwrap();
|
||||
receiver.recv().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WebGLRenderingContext {
|
||||
|
@ -958,6 +1187,19 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
// Handle GetParameter getters injected via WebGL extensions
|
||||
if let Some(query_handler) = self.extension_manager.get_query_parameter_handler(parameter) {
|
||||
match query_handler(cx, &self) {
|
||||
Ok(value) => {
|
||||
return value;
|
||||
},
|
||||
Err(error) => {
|
||||
self.webgl_error(error);
|
||||
return NullValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (sender, receiver) = webrender_traits::channel::msg_channel().unwrap();
|
||||
self.ipc_renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::GetParameter(parameter, sender)))
|
||||
|
@ -1019,14 +1261,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.14
|
||||
fn GetSupportedExtensions(&self) -> Option<Vec<DOMString>> {
|
||||
Some(vec![])
|
||||
self.extension_manager.init_once(|| {
|
||||
self.get_gl_extensions()
|
||||
});
|
||||
let extensions = self.extension_manager.get_suported_extensions();
|
||||
Some(extensions.iter().map(|name| DOMString::from(*name)).collect())
|
||||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.14
|
||||
unsafe fn GetExtension(&self, _cx: *mut JSContext, _name: DOMString)
|
||||
unsafe fn GetExtension(&self, _cx: *mut JSContext, name: DOMString)
|
||||
-> Option<NonZero<*mut JSObject>> {
|
||||
None
|
||||
self.extension_manager.init_once(|| {
|
||||
self.get_gl_extensions()
|
||||
});
|
||||
self.extension_manager.get_or_init_extension(&name, self)
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
|
||||
|
@ -1627,6 +1876,23 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5
|
||||
fn DeleteBuffer(&self, buffer: Option<&WebGLBuffer>) {
|
||||
if let Some(buffer) = buffer {
|
||||
if buffer.is_attached_to_vao() {
|
||||
// WebGL spec: The buffers attached to VAOs should still not be deleted.
|
||||
// They are deleted after the VAO is deleted.
|
||||
buffer.set_pending_delete();
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove deleted buffer from bound attrib buffers.
|
||||
let attrib_ids: Vec<_> = self.bound_attrib_buffers.borrow().iter()
|
||||
.filter(|&(_, v)| v.id() == buffer.id())
|
||||
.map(|(&k, _)| k)
|
||||
.collect();
|
||||
for id in attrib_ids {
|
||||
self.bound_attrib_buffers.borrow_mut().remove(&id);
|
||||
}
|
||||
|
||||
// Delete buffer.
|
||||
handle_object_deletion!(self, self.bound_buffer_array, buffer,
|
||||
Some(WebGLCommand::BindBuffer(constants::ARRAY_BUFFER, None)));
|
||||
handle_object_deletion!(self, self.bound_buffer_element_array, buffer,
|
||||
|
@ -1989,6 +2255,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
return result.get()
|
||||
}
|
||||
|
||||
if pname == constants::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING {
|
||||
rooted!(in(cx) let mut jsval = NullValue());
|
||||
if let Some(buffer) = self.bound_attrib_buffers.borrow().get(&index) {
|
||||
buffer.to_jsval(cx, jsval.handle_mut());
|
||||
}
|
||||
return jsval.get();
|
||||
}
|
||||
|
||||
let (sender, receiver) = webrender_traits::channel::msg_channel().unwrap();
|
||||
self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetVertexAttrib(index, pname, sender))).unwrap();
|
||||
|
||||
|
@ -2006,6 +2280,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
}
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10
|
||||
fn GetVertexAttribOffset(&self, index: u32, pname: u32) -> i64 {
|
||||
let (sender, receiver) = webrender_traits::channel::msg_channel().unwrap();
|
||||
self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::GetVertexAttribOffset(index, pname, sender))).unwrap();
|
||||
|
||||
handle_potential_webgl_error!(self, receiver.recv().unwrap(), 0) as i64
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3
|
||||
fn Hint(&self, target: u32, mode: u32) {
|
||||
if target != constants::GENERATE_MIPMAP_HINT {
|
||||
|
@ -2784,9 +3066,13 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
if size < 1 || size > 4 {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
if self.bound_buffer_array.get().is_none() {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
|
||||
let buffer_array = match self.bound_buffer_array.get() {
|
||||
Some(buffer) => buffer,
|
||||
None => {
|
||||
return self.webgl_error(InvalidOperation);
|
||||
}
|
||||
};
|
||||
|
||||
// stride and offset must be multiple of data_type
|
||||
match data_type {
|
||||
|
@ -2805,6 +3091,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
}
|
||||
|
||||
self.bound_attrib_buffers.borrow_mut().insert(attrib_id, JS::from_ref(&*buffer_array));
|
||||
|
||||
let msg = CanvasMsg::WebGL(
|
||||
WebGLCommand::VertexAttribPointer(attrib_id, size, data_type, normalized, stride, offset as u32));
|
||||
self.ipc_renderer.send(msg).unwrap()
|
||||
|
@ -2834,6 +3122,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
format: u32,
|
||||
data_type: u32,
|
||||
data_ptr: *mut JSObject) -> Fallible<()> {
|
||||
if !self.extension_manager.is_tex_type_enabled(data_type) {
|
||||
return Ok(self.webgl_error(InvalidEnum));
|
||||
}
|
||||
|
||||
let data = if data_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
|
@ -2885,10 +3177,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
return Ok(self.webgl_error(InvalidOperation));
|
||||
}
|
||||
|
||||
if !self.validate_filterable_texture(&texture, target, level, format, width, height, data_type) {
|
||||
return Ok(()); // The validator sets the correct error for use
|
||||
}
|
||||
|
||||
let pixels = self.prepare_pixels(format, data_type, width, height,
|
||||
unpacking_alignment, false, false, buff);
|
||||
|
||||
self.tex_image_2d(texture, target, data_type, format,
|
||||
self.tex_image_2d(&texture, target, data_type, format,
|
||||
level, width, height, border, unpacking_alignment, pixels);
|
||||
|
||||
Ok(())
|
||||
|
@ -2902,6 +3198,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
format: u32,
|
||||
data_type: u32,
|
||||
source: Option<ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement>) -> Fallible<()> {
|
||||
if !self.extension_manager.is_tex_type_enabled(data_type) {
|
||||
return Ok(self.webgl_error(InvalidEnum));
|
||||
}
|
||||
|
||||
// Get pixels from image source
|
||||
let (pixels, size, premultiplied) = match self.get_image_pixels(source) {
|
||||
Ok((pixels, size, premultiplied)) => (pixels, size, premultiplied),
|
||||
|
@ -2927,11 +3227,15 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
Err(_) => return Ok(()), // NB: The validator sets the correct error for us.
|
||||
};
|
||||
|
||||
if !self.validate_filterable_texture(&texture, target, level, format, width, height, data_type) {
|
||||
return Ok(()); // The validator sets the correct error for use
|
||||
}
|
||||
|
||||
let unpacking_alignment = 1;
|
||||
let pixels = self.prepare_pixels(format, data_type, width, height,
|
||||
unpacking_alignment, premultiplied, true, pixels);
|
||||
|
||||
self.tex_image_2d(texture, target, data_type, format,
|
||||
self.tex_image_2d(&texture, target, data_type, format,
|
||||
level, width, height, border, 1, pixels);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2955,7 +3259,6 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
Some(try!(fallible_array_buffer_view_to_vec(cx, data_ptr)))
|
||||
};
|
||||
|
||||
|
||||
let validator = TexImage2DValidator::new(self, target, level,
|
||||
format, width, height,
|
||||
0, format, data_type);
|
||||
|
|
|
@ -42,6 +42,9 @@ pub struct WebGLTexture {
|
|||
/// Face count can only be 1 or 6
|
||||
face_count: Cell<u8>,
|
||||
base_mipmap_level: u32,
|
||||
// Store information for min and mag filters
|
||||
min_filter: Cell<Option<u32>>,
|
||||
mag_filter: Cell<Option<u32>>,
|
||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||
renderer: IpcSender<CanvasMsg>,
|
||||
}
|
||||
|
@ -57,6 +60,8 @@ impl WebGLTexture {
|
|||
is_deleted: Cell::new(false),
|
||||
face_count: Cell::new(0),
|
||||
base_mipmap_level: 0,
|
||||
min_filter: Cell::new(None),
|
||||
mag_filter: Cell::new(None),
|
||||
image_info_array: DOMRefCell::new([ImageInfo::new(); MAX_LEVEL_COUNT * MAX_FACE_COUNT]),
|
||||
renderer: renderer,
|
||||
}
|
||||
|
@ -209,6 +214,7 @@ impl WebGLTexture {
|
|||
constants::LINEAR_MIPMAP_NEAREST |
|
||||
constants::NEAREST_MIPMAP_LINEAR |
|
||||
constants::LINEAR_MIPMAP_LINEAR => {
|
||||
self.min_filter.set(Some(int_value as u32));
|
||||
self.renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value)))
|
||||
.unwrap();
|
||||
|
@ -222,6 +228,7 @@ impl WebGLTexture {
|
|||
match int_value as u32 {
|
||||
constants::NEAREST |
|
||||
constants::LINEAR => {
|
||||
self.mag_filter.set(Some(int_value as u32));
|
||||
self.renderer
|
||||
.send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value)))
|
||||
.unwrap();
|
||||
|
@ -251,6 +258,19 @@ impl WebGLTexture {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_using_linear_filtering(&self) -> bool {
|
||||
let filters = [self.min_filter.get(), self.mag_filter.get()];
|
||||
filters.iter().any(|filter| {
|
||||
match *filter {
|
||||
Some(constants::LINEAR) |
|
||||
Some(constants::NEAREST_MIPMAP_LINEAR) |
|
||||
Some(constants::LINEAR_MIPMAP_NEAREST) |
|
||||
Some(constants::LINEAR_MIPMAP_LINEAR) => true,
|
||||
_=> false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn populate_mip_chain(&self, first_level: u32, last_level: u32) -> WebGLResult<()> {
|
||||
let base_image_info = self.image_info_at_face(0, first_level);
|
||||
if !base_image_info.is_initialized() {
|
||||
|
@ -408,7 +428,7 @@ impl ImageInfo {
|
|||
self.depth.is_power_of_two()
|
||||
}
|
||||
|
||||
fn is_initialized(&self) -> bool {
|
||||
pub fn is_initialized(&self) -> bool {
|
||||
self.is_initialized
|
||||
}
|
||||
|
||||
|
|
11
components/script/dom/webidls/OESTextureFloat.webidl
Normal file
11
components/script/dom/webidls/OESTextureFloat.webidl
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* 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/OES_texture_float/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface OESTextureFloat {
|
||||
};
|
11
components/script/dom/webidls/OESTextureFloatLinear.webidl
Normal file
11
components/script/dom/webidls/OESTextureFloatLinear.webidl
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* 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/OES_texture_float_linear/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface OESTextureFloatLinear {
|
||||
};
|
12
components/script/dom/webidls/OESTextureHalfFloat.webidl
Normal file
12
components/script/dom/webidls/OESTextureHalfFloat.webidl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* 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/OES_texture_half_float/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface OESTextureHalfFloat {
|
||||
const GLenum HALF_FLOAT_OES = 0x8D61;
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
/* 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/OES_texture_half_float_linear/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface OESTextureHalfFloatLinear {
|
||||
};
|
17
components/script/dom/webidls/OESVertexArrayObject.webidl
Normal file
17
components/script/dom/webidls/OESVertexArrayObject.webidl
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* 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/OES_vertex_array_object/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface OESVertexArrayObject {
|
||||
const unsigned long VERTEX_ARRAY_BINDING_OES = 0x85B5;
|
||||
|
||||
WebGLVertexArrayObjectOES? createVertexArrayOES();
|
||||
void deleteVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject);
|
||||
boolean isVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject);
|
||||
void bindVertexArrayOES(WebGLVertexArrayObjectOES? arrayObject);
|
||||
};
|
|
@ -608,7 +608,7 @@ interface WebGLRenderingContextBase
|
|||
|
||||
any getVertexAttrib(GLuint index, GLenum pname);
|
||||
|
||||
//[WebGLHandlesContextLoss] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname);
|
||||
[WebGLHandlesContextLoss] GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname);
|
||||
|
||||
void hint(GLenum target, GLenum mode);
|
||||
[WebGLHandlesContextLoss] GLboolean isBuffer(WebGLBuffer? buffer);
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/* 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 scraped from the Khronos specification:
|
||||
* https://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/
|
||||
*/
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface WebGLVertexArrayObjectOES: WebGLObject {
|
||||
};
|
|
@ -48,6 +48,8 @@ extern crate encoding;
|
|||
extern crate euclid;
|
||||
extern crate fnv;
|
||||
extern crate gfx_traits;
|
||||
extern crate gleam;
|
||||
extern crate half;
|
||||
#[macro_use] extern crate heapsize;
|
||||
#[macro_use] extern crate heapsize_derive;
|
||||
#[macro_use] extern crate html5ever;
|
||||
|
|
|
@ -58,6 +58,7 @@ FILE_PATTERNS_TO_IGNORE = ["*.#*", "*.pyc", "fake-ld.sh"]
|
|||
SPEC_BASE_PATH = "components/script/dom/"
|
||||
|
||||
WEBIDL_STANDARDS = [
|
||||
"//www.khronos.org/registry/webgl/extensions",
|
||||
"//www.khronos.org/registry/webgl/specs",
|
||||
"//developer.mozilla.org/en-US/docs/Web/API",
|
||||
"//dev.w3.org/2006/webapi",
|
||||
|
|
|
@ -15,9 +15,6 @@
|
|||
[WebGL test #4: Property either does not exist or is not a function: getUniform]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #5: Property either does not exist or is not a function: getVertexAttribOffset]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #6: Property either does not exist or is not a function: isContextLost]
|
||||
[WebGL test #5: Property either does not exist or is not a function: isContextLost]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[oes-texture-float-linear.html]
|
||||
type: testharness
|
||||
[WebGL test #0: Unable to fetch WebGL rendering context for Canvas]
|
||||
expected: FAIL
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
[oes-texture-float-with-canvas.html]
|
||||
type: testharness
|
||||
[WebGL test #0: Unable to fetch WebGL rendering context for Canvas]
|
||||
expected: FAIL
|
||||
|
||||
expected: ERROR
|
||||
[Overall test]
|
||||
expected: NOTRUN
|
|
@ -1,5 +0,0 @@
|
|||
[oes-texture-float-with-image-data.html]
|
||||
type: testharness
|
||||
[WebGL test #0: Unable to fetch WebGL rendering context for Canvas]
|
||||
expected: FAIL
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
[oes-texture-float-with-image.html]
|
||||
type: testharness
|
||||
[WebGL test #0: Unable to fetch WebGL rendering context for Canvas]
|
||||
expected:
|
||||
if os == "linux": FAIL
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
[oes-texture-float.html]
|
||||
type: testharness
|
||||
disabled: flaky
|
|
@ -1,5 +0,0 @@
|
|||
[oes-texture-half-float-linear.html]
|
||||
type: testharness
|
||||
[WebGL test #0: Unable to fetch WebGL rendering context for Canvas]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
[oes-texture-half-float-with-canvas.html]
|
||||
type: testharness
|
||||
expected: ERROR
|
||||
[Overall test]
|
||||
expected: NOTRUN
|
|
@ -1,5 +0,0 @@
|
|||
[oes-texture-half-float-with-image-data.html]
|
||||
type: testharness
|
||||
[WebGL test #0: Unable to fetch WebGL rendering context for Canvas]
|
||||
expected: FAIL
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
[oes-texture-half-float-with-video.html]
|
||||
type: testharness
|
||||
[WebGL test #0: Unable to fetch WebGL rendering context for Canvas]
|
||||
expected:
|
||||
if os == "linux": FAIL
|
||||
|
||||
disabled: flaky
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[oes-texture-half-float.html]
|
||||
type: testharness
|
||||
[WebGL test #2: successfullyParsed should be true (of type boolean). Was undefined (of type undefined).]
|
||||
expected: FAIL
|
||||
|
|
@ -1,3 +1,38 @@
|
|||
[tex-image-with-format-and-type.html]
|
||||
type: testharness
|
||||
expected: CRASH
|
||||
|
||||
[WebGL test #6: LUMINANCE/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #7: LUMINANCE_ALPHA/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #14: LUMINANCE/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #15: LUMINANCE_ALPHA/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #22: LUMINANCE/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #23: LUMINANCE_ALPHA/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #30: LUMINANCE/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #31: LUMINANCE_ALPHA/UNSIGNED_BYTE should maintain full precision of data]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #65: UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_SHORT_4_4_4_4]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #66: UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_SHORT_5_5_5_1]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #69: UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_SHORT_4_4_4_4]
|
||||
expected: FAIL
|
||||
|
||||
[WebGL test #70: UNPACK_PREMULTIPLY_ALPHA_WEBGL with RGBA/UNSIGNED_SHORT_5_5_5_1]
|
||||
expected: FAIL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue