mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Implement WebGL extensions.
This commit is contained in:
parent
ac99a48aea
commit
32e23c4db4
40 changed files with 1346 additions and 86 deletions
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()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue