aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/bindings/trace.rs14
-rw-r--r--components/script/dom/document.rs24
-rw-r--r--components/script/dom/performanceresourcetiming.rs3
-rw-r--r--components/script/dom/webgl2renderingcontext.rs2
-rw-r--r--components/script/dom/webgl_validations/tex_image_2d.rs4
-rw-r--r--components/script/dom/webglframebuffer.rs143
-rw-r--r--components/script/dom/webglprogram.rs2
-rw-r--r--components/script/dom/webglrenderbuffer.rs2
-rw-r--r--components/script/dom/webglrenderingcontext.rs98
-rw-r--r--components/script/dom/webgltexture.rs75
-rw-r--r--components/script/dom/webgluniformlocation.rs10
-rw-r--r--components/script/dom/xrsession.rs31
-rw-r--r--components/script/dom/xrwebgllayer.rs126
13 files changed, 282 insertions, 252 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 4b79bc7085b..7869d1499ac 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -47,11 +47,10 @@ use canvas_traits::canvas::{
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
use canvas_traits::webgl::WebGLVertexArrayId;
use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, GlType, TexDataType, TexFormat};
-use canvas_traits::webgl::{GLFormats, GLLimits, WebGLQueryId, WebGLSamplerId};
-use canvas_traits::webgl::{
- WebGLBufferId, WebGLChan, WebGLContextId, WebGLContextShareMode, WebGLError,
-};
+use canvas_traits::webgl::{GLLimits, WebGLQueryId, WebGLSamplerId};
+use canvas_traits::webgl::{WebGLBufferId, WebGLChan, WebGLContextId, WebGLError};
use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsgSender, WebGLPipeline, WebGLProgramId};
+use canvas_traits::webgl::{WebGLOpaqueFramebufferId, WebGLTransparentFramebufferId};
use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender};
use canvas_traits::webgl::{WebGLShaderId, WebGLSyncId, WebGLTextureId, WebGLVersion};
use content_security_policy::CspList;
@@ -147,6 +146,7 @@ use time::{Duration, Timespec};
use uuid::Uuid;
use webrender_api::{DocumentId, ImageKey, RenderApiSender};
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
+use webxr_api::SwapChainId as WebXRSwapChainId;
/// A trait to allow tracing (only) DOM objects.
pub unsafe trait JSTraceable {
@@ -451,7 +451,7 @@ unsafe_no_jsmanaged_fields!(StorageType);
unsafe_no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
unsafe_no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
unsafe_no_jsmanaged_fields!(RepetitionStyle);
-unsafe_no_jsmanaged_fields!(WebGLError, GLFormats, GLLimits, GlType);
+unsafe_no_jsmanaged_fields!(WebGLError, GLLimits, GlType);
unsafe_no_jsmanaged_fields!(TimeProfilerChan);
unsafe_no_jsmanaged_fields!(MemProfilerChan);
unsafe_no_jsmanaged_fields!(PseudoElement);
@@ -486,8 +486,9 @@ unsafe_no_jsmanaged_fields!(DocumentId);
unsafe_no_jsmanaged_fields!(ImageKey);
unsafe_no_jsmanaged_fields!(WebGLBufferId);
unsafe_no_jsmanaged_fields!(WebGLChan);
-unsafe_no_jsmanaged_fields!(WebGLContextShareMode);
unsafe_no_jsmanaged_fields!(WebGLFramebufferId);
+unsafe_no_jsmanaged_fields!(WebGLOpaqueFramebufferId);
+unsafe_no_jsmanaged_fields!(WebGLTransparentFramebufferId);
unsafe_no_jsmanaged_fields!(WebGLMsgSender);
unsafe_no_jsmanaged_fields!(WebGLPipeline);
unsafe_no_jsmanaged_fields!(WebGLProgramId);
@@ -500,6 +501,7 @@ unsafe_no_jsmanaged_fields!(WebGLTextureId);
unsafe_no_jsmanaged_fields!(WebGLVertexArrayId);
unsafe_no_jsmanaged_fields!(WebGLVersion);
unsafe_no_jsmanaged_fields!(WebGLSLVersion);
+unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
unsafe_no_jsmanaged_fields!(MediaList);
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand);
unsafe_no_jsmanaged_fields!(
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index fd5994925c1..0efb0856098 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -98,6 +98,7 @@ use crate::dom::treewalker::TreeWalker;
use crate::dom::uievent::UIEvent;
use crate::dom::virtualmethods::vtable_for;
use crate::dom::webglcontextevent::WebGLContextEvent;
+use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::wheelevent::WheelEvent;
use crate::dom::window::{ReflowReason, Window};
use crate::dom::windowproxy::WindowProxy;
@@ -109,7 +110,7 @@ use crate::stylesheet_set::StylesheetSetRef;
use crate::task::TaskBox;
use crate::task_source::{TaskSource, TaskSourceName};
use crate::timers::OneshotTimerCallback;
-use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg};
+use canvas_traits::webgl::{self, SwapChainId, WebGLContextId, WebGLMsg};
use content_security_policy::{self as csp, CspList};
use cookie::Cookie;
use devtools_traits::ScriptToDevtoolsControlMsg;
@@ -399,7 +400,7 @@ pub struct Document {
/// hosting the media controls UI.
media_controls: DomRefCell<HashMap<String, Dom<ShadowRoot>>>,
/// List of all WebGL context IDs that need flushing.
- dirty_webgl_contexts: DomRefCell<HashSet<WebGLContextId>>,
+ dirty_webgl_contexts: DomRefCell<HashMap<WebGLContextId, Dom<WebGLRenderingContext>>>,
/// https://html.spec.whatwg.org/multipage/#concept-document-csp-list
#[ignore_malloc_size_of = "Defined in rust-content-security-policy"]
csp_list: DomRefCell<Option<CspList>>,
@@ -2486,15 +2487,26 @@ impl Document {
}
}
- pub fn add_dirty_canvas(&self, context_id: WebGLContextId) {
- self.dirty_webgl_contexts.borrow_mut().insert(context_id);
+ pub fn add_dirty_canvas(&self, context: &WebGLRenderingContext) {
+ self.dirty_webgl_contexts
+ .borrow_mut()
+ .entry(context.context_id())
+ .or_insert_with(|| Dom::from_ref(context));
}
pub fn flush_dirty_canvases(&self) {
- let dirty_context_ids: Vec<_> = self.dirty_webgl_contexts.borrow_mut().drain().collect();
+ let dirty_context_ids: Vec<_> = self
+ .dirty_webgl_contexts
+ .borrow_mut()
+ .drain()
+ .filter(|(_, context)| context.onscreen())
+ .map(|(id, _)| SwapChainId::Context(id))
+ .collect();
+
if dirty_context_ids.is_empty() {
return;
}
+
let (sender, receiver) = webgl::webgl_channel().unwrap();
self.window
.webgl_chan()
@@ -2797,7 +2809,7 @@ impl Document {
shadow_roots: DomRefCell::new(HashSet::new()),
shadow_roots_styles_changed: Cell::new(false),
media_controls: DomRefCell::new(HashMap::new()),
- dirty_webgl_contexts: DomRefCell::new(HashSet::new()),
+ dirty_webgl_contexts: DomRefCell::new(HashMap::new()),
csp_list: DomRefCell::new(None),
}
}
diff --git a/components/script/dom/performanceresourcetiming.rs b/components/script/dom/performanceresourcetiming.rs
index 735d13a31f4..586515d4365 100644
--- a/components/script/dom/performanceresourcetiming.rs
+++ b/components/script/dom/performanceresourcetiming.rs
@@ -55,7 +55,6 @@ pub struct PerformanceResourceTiming {
decoded_body_size: u64, //size in octets
}
-// TODO(#21255): duration
// TODO(#21269): next_hop
// TODO(#21264): worker_start
// TODO(#21258): fetch_start
@@ -115,7 +114,7 @@ impl PerformanceResourceTiming {
DOMString::from(url.into_string()),
DOMString::from("resource"),
resource_timing.start_time as f64,
- 0.,
+ resource_timing.response_end as f64 - resource_timing.start_time as f64,
),
initiator_type: initiator_type,
next_hop: next_hop,
diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs
index 63cfd0bc530..4c7d9fb857a 100644
--- a/components/script/dom/webgl2renderingcontext.rs
+++ b/components/script/dom/webgl2renderingcontext.rs
@@ -1426,6 +1426,6 @@ impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGL2RenderingConte
#[allow(unsafe_code)]
unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource {
let this = &*self.unsafe_get();
- HTMLCanvasDataSource::WebGL((*this.base.to_layout().unsafe_get()).layout_handle())
+ (*this.base.to_layout().unsafe_get()).layout_handle()
}
}
diff --git a/components/script/dom/webgl_validations/tex_image_2d.rs b/components/script/dom/webgl_validations/tex_image_2d.rs
index 329ffd10349..fc5919132cf 100644
--- a/components/script/dom/webgl_validations/tex_image_2d.rs
+++ b/components/script/dom/webgl_validations/tex_image_2d.rs
@@ -613,7 +613,7 @@ impl<'a> WebGLValidator for CompressedTexSubImage2DValidator<'a> {
compression,
} = self.compression_validator.validate()?;
- let tex_info = texture.image_info_for_target(&target, level);
+ let tex_info = texture.image_info_for_target(&target, level).unwrap();
// GL_INVALID_VALUE is generated if:
// - xoffset or yoffset is less than 0
@@ -630,7 +630,7 @@ impl<'a> WebGLValidator for CompressedTexSubImage2DValidator<'a> {
// GL_INVALID_OPERATION is generated if format does not match
// internal_format.
- if compression.format != tex_info.internal_format().unwrap() {
+ if compression.format != tex_info.internal_format() {
context.webgl_error(InvalidOperation);
return Err(TexImageValidationError::TextureFormatMismatch);
}
diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs
index 3a31e99be33..df9e194962e 100644
--- a/components/script/dom/webglframebuffer.rs
+++ b/components/script/dom/webglframebuffer.rs
@@ -8,15 +8,20 @@ use crate::dom::bindings::codegen::Bindings::WebGLFramebufferBinding;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
-use crate::dom::bindings::root::{Dom, DomRoot};
+use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::webglobject::WebGLObject;
use crate::dom::webglrenderbuffer::WebGLRenderbuffer;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::webgltexture::WebGLTexture;
+use crate::dom::xrsession::XRSession;
use canvas_traits::webgl::{webgl_channel, WebGLError, WebGLResult};
-use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFramebufferId};
+use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest};
+use canvas_traits::webgl::{WebGLFramebufferId, WebGLOpaqueFramebufferId};
use dom_struct::dom_struct;
+use euclid::Size2D;
use std::cell::Cell;
+use webxr_api::SwapChainId as WebXRSwapChainId;
+use webxr_api::Viewport;
pub enum CompleteForRendering {
Complete,
@@ -92,6 +97,9 @@ pub struct WebGLFramebuffer {
stencil: DomRefCell<Option<WebGLFramebufferAttachment>>,
depthstencil: DomRefCell<Option<WebGLFramebufferAttachment>>,
is_initialized: Cell<bool>,
+ // Framebuffers for XR keep a reference to the XR session.
+ // https://github.com/immersive-web/webxr/issues/856
+ xr_session: MutNullableDom<XRSession>,
}
impl WebGLFramebuffer {
@@ -108,16 +116,37 @@ impl WebGLFramebuffer {
stencil: DomRefCell::new(None),
depthstencil: DomRefCell::new(None),
is_initialized: Cell::new(false),
+ xr_session: Default::default(),
}
}
pub fn maybe_new(context: &WebGLRenderingContext) -> Option<DomRoot<Self>> {
let (sender, receiver) = webgl_channel().unwrap();
context.send_command(WebGLCommand::CreateFramebuffer(sender));
- receiver
- .recv()
- .unwrap()
- .map(|id| WebGLFramebuffer::new(context, id))
+ let id = receiver.recv().unwrap()?;
+ let framebuffer = WebGLFramebuffer::new(context, WebGLFramebufferId::Transparent(id));
+ Some(framebuffer)
+ }
+
+ // TODO: depth, stencil and alpha
+ // https://github.com/servo/servo/issues/24498
+ pub fn maybe_new_webxr(
+ session: &XRSession,
+ context: &WebGLRenderingContext,
+ size: Size2D<i32, Viewport>,
+ ) -> Option<(WebXRSwapChainId, DomRoot<Self>)> {
+ let (sender, receiver) = webgl_channel().unwrap();
+ let _ = context
+ .webgl_sender()
+ .send_create_webxr_swap_chain(size.to_untyped(), sender);
+ let swap_chain_id = receiver.recv().unwrap()?;
+ let framebuffer_id =
+ WebGLFramebufferId::Opaque(WebGLOpaqueFramebufferId::WebXR(swap_chain_id));
+ let framebuffer = WebGLFramebuffer::new(context, framebuffer_id);
+ framebuffer.size.set(Some((size.width, size.height)));
+ framebuffer.status.set(constants::FRAMEBUFFER_COMPLETE);
+ framebuffer.xr_session.set(Some(session));
+ Some((swap_chain_id, framebuffer))
}
pub fn new(context: &WebGLRenderingContext, id: WebGLFramebufferId) -> DomRoot<Self> {
@@ -134,11 +163,25 @@ impl WebGLFramebuffer {
self.id
}
+ fn is_in_xr_session(&self) -> bool {
+ self.xr_session.get().is_some()
+ }
+
+ pub fn validate_transparent(&self) -> WebGLResult<()> {
+ if self.is_in_xr_session() {
+ Err(WebGLError::InvalidOperation)
+ } else {
+ Ok(())
+ }
+ }
+
pub fn bind(&self, target: u32) {
- // Update the framebuffer status on binding. It may have
- // changed if its attachments were resized or deleted while
- // we've been unbound.
- self.update_status();
+ if !self.is_in_xr_session() {
+ // Update the framebuffer status on binding. It may have
+ // changed if its attachments were resized or deleted while
+ // we've been unbound.
+ self.update_status();
+ }
self.target.set(Some(target));
self.upcast::<WebGLObject>()
@@ -221,12 +264,16 @@ impl WebGLFramebuffer {
Some(WebGLFramebufferAttachment::Texture {
texture: ref att_tex,
level,
- }) => {
- let info = att_tex.image_info_at_face(0, level as u32);
- (
- info.internal_format().map(|t| t.as_gl_constant()),
+ }) => match att_tex.image_info_at_face(0, level as u32) {
+ Some(info) => (
+ Some(info.internal_format().as_gl_constant()),
Some((info.width() as i32, info.height() as i32)),
- )
+ ),
+ None => {
+ self.status
+ .set(constants::FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
+ return;
+ },
},
None => (None, None),
};
@@ -267,7 +314,17 @@ impl WebGLFramebuffer {
}
pub fn check_status(&self) -> u32 {
- return self.status.get();
+ // For opaque framebuffers, check to see if the XR session is currently processing an rAF
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ if let Some(xr_session) = self.xr_session.get() {
+ if xr_session.is_outside_raf() {
+ constants::FRAMEBUFFER_UNSUPPORTED
+ } else {
+ constants::FRAMEBUFFER_COMPLETE
+ }
+ } else {
+ self.status.get()
+ }
}
pub fn check_status_for_rendering(&self) -> CompleteForRendering {
@@ -276,6 +333,12 @@ impl WebGLFramebuffer {
return CompleteForRendering::Incomplete;
}
+ // XR framebuffers are complete inside an rAF
+ // https://github.com/immersive-web/webxr/issues/854
+ if self.xr_session.get().is_some() {
+ return CompleteForRendering::Complete;
+ }
+
if self.color.borrow().is_none() {
return CompleteForRendering::MissingColorAttachment;
}
@@ -309,6 +372,10 @@ impl WebGLFramebuffer {
}
pub fn renderbuffer(&self, attachment: u32, rb: Option<&WebGLRenderbuffer>) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let binding = self
.attachment_binding(attachment)
.ok_or(WebGLError::InvalidEnum)?;
@@ -337,7 +404,7 @@ impl WebGLFramebuffer {
));
if rb.is_none() {
- self.detach_binding(binding, attachment);
+ self.detach_binding(binding, attachment)?;
}
self.update_status();
@@ -349,14 +416,19 @@ impl WebGLFramebuffer {
&self,
binding: &DomRefCell<Option<WebGLFramebufferAttachment>>,
attachment: u32,
- ) {
+ ) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
if let Some(att) = &*binding.borrow() {
att.detach();
}
*binding.borrow_mut() = None;
if INTERESTING_ATTACHMENT_POINTS.contains(&attachment) {
- self.reattach_depth_stencil();
+ self.reattach_depth_stencil()?;
}
+ Ok(())
}
fn attachment_binding(
@@ -372,7 +444,11 @@ impl WebGLFramebuffer {
}
}
- fn reattach_depth_stencil(&self) {
+ fn reattach_depth_stencil(&self) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let reattach = |attachment: &WebGLFramebufferAttachment, attachment_point| {
let context = self.upcast::<WebGLObject>().context();
match *attachment {
@@ -411,6 +487,7 @@ impl WebGLFramebuffer {
if let Some(ref depth_stencil) = *self.depthstencil.borrow() {
reattach(depth_stencil, constants::DEPTH_STENCIL_ATTACHMENT);
}
+ Ok(())
}
pub fn attachment(&self, attachment: u32) -> Option<WebGLFramebufferAttachmentRoot> {
@@ -428,6 +505,10 @@ impl WebGLFramebuffer {
texture: Option<&WebGLTexture>,
level: i32,
) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let binding = self
.attachment_binding(attachment)
.ok_or(WebGLError::InvalidEnum)?;
@@ -498,7 +579,7 @@ impl WebGLFramebuffer {
));
if texture.is_none() {
- self.detach_binding(binding, attachment);
+ self.detach_binding(binding, attachment)?;
}
self.update_status();
@@ -563,7 +644,11 @@ impl WebGLFramebuffer {
}
}
- pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) {
+ pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let mut depth_or_stencil_updated = false;
self.with_matching_renderbuffers(rb, |att, name| {
depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name);
@@ -575,11 +660,16 @@ impl WebGLFramebuffer {
});
if depth_or_stencil_updated {
- self.reattach_depth_stencil();
+ self.reattach_depth_stencil()?;
}
+ Ok(())
}
- pub fn detach_texture(&self, texture: &WebGLTexture) {
+ pub fn detach_texture(&self, texture: &WebGLTexture) -> WebGLResult<()> {
+ // Opaque framebuffers cannot have their attachments changed
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ self.validate_transparent()?;
+
let mut depth_or_stencil_updated = false;
self.with_matching_textures(texture, |att, name| {
depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name);
@@ -591,8 +681,9 @@ impl WebGLFramebuffer {
});
if depth_or_stencil_updated {
- self.reattach_depth_stencil();
+ self.reattach_depth_stencil()?;
}
+ Ok(())
}
pub fn invalidate_renderbuffer(&self, rb: &WebGLRenderbuffer) {
@@ -615,7 +706,7 @@ impl WebGLFramebuffer {
impl Drop for WebGLFramebuffer {
fn drop(&mut self) {
- self.delete(true);
+ let _ = self.delete(true);
}
}
diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs
index bf198e5382c..6863bc89e53 100644
--- a/components/script/dom/webglprogram.rs
+++ b/components/script/dom/webglprogram.rs
@@ -392,10 +392,12 @@ impl WebGLProgram {
sender,
));
let location = receiver.recv().unwrap();
+ let context_id = self.upcast::<WebGLObject>().context().context_id();
Ok(Some(WebGLUniformLocation::new(
self.global().as_window(),
location,
+ context_id,
self.id,
self.link_generation.get(),
size,
diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs
index 07afdbccb44..ca75f83c336 100644
--- a/components/script/dom/webglrenderbuffer.rs
+++ b/components/script/dom/webglrenderbuffer.rs
@@ -106,7 +106,7 @@ impl WebGLRenderbuffer {
let currently_bound_framebuffer =
self.upcast::<WebGLObject>().context().bound_framebuffer();
if let Some(fb) = currently_bound_framebuffer {
- fb.detach_renderbuffer(self);
+ let _ = fb.detach_renderbuffer(self);
}
let context = self.upcast::<WebGLObject>().context();
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index f19664ad0ad..b5faecc7371 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -54,11 +54,11 @@ use crate::script_runtime::JSContext as SafeJSContext;
use backtrace::Backtrace;
use canvas_traits::webgl::WebGLError::*;
use canvas_traits::webgl::{
- webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLFormats, GLLimits,
- GlType, Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand,
- WebGLCommandBacktrace, WebGLContextId, WebGLContextShareMode, WebGLError,
- WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLProgramId, WebGLResult,
- WebGLSLVersion, WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment,
+ webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType,
+ Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand,
+ WebGLCommandBacktrace, WebGLContextId, WebGLError, WebGLFramebufferBindingRequest, WebGLMsg,
+ WebGLMsgSender, WebGLOpaqueFramebufferId, WebGLProgramId, WebGLResult, WebGLSLVersion,
+ WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment,
};
use dom_struct::dom_struct;
use embedder_traits::EventLoopWaker;
@@ -81,6 +81,7 @@ use std::cell::Cell;
use std::cmp;
use std::ptr::{self, NonNull};
use std::rc::Rc;
+use webxr_api::SwapChainId as WebXRSwapChainId;
// From the GLES 2.0.25 spec, page 85:
//
@@ -130,10 +131,9 @@ pub struct WebGLRenderingContext {
webgl_sender: WebGLMessageSender,
#[ignore_malloc_size_of = "Defined in webrender"]
webrender_image: webrender_api::ImageKey,
- share_mode: WebGLContextShareMode,
webgl_version: WebGLVersion,
glsl_version: WebGLSLVersion,
- #[ignore_malloc_size_of = "Defined in offscreen_gl_context"]
+ #[ignore_malloc_size_of = "Defined in surfman"]
limits: GLLimits,
canvas: Dom<HTMLCanvasElement>,
#[ignore_malloc_size_of = "Defined in canvas_traits"]
@@ -160,7 +160,6 @@ pub struct WebGLRenderingContext {
current_vao: MutNullableDom<WebGLVertexArrayObjectOES>,
textures: Textures,
api_type: GlType,
- framebuffer_format: GLFormats,
}
impl WebGLRenderingContext {
@@ -195,7 +194,6 @@ impl WebGLRenderingContext {
window.get_event_loop_waker(),
),
webrender_image: ctx_data.image_key,
- share_mode: ctx_data.share_mode,
webgl_version,
glsl_version: ctx_data.glsl_version,
limits: ctx_data.limits,
@@ -220,7 +218,6 @@ impl WebGLRenderingContext {
current_vao: Default::default(),
textures: Textures::new(max_combined_texture_image_units),
api_type: ctx_data.api_type,
- framebuffer_format: ctx_data.framebuffer_format,
}
})
}
@@ -292,7 +289,7 @@ impl WebGLRenderingContext {
self.send_command(WebGLCommand::Scissor(rect.0, rect.1, rect.2, rect.3));
// Bound texture must not change when the canvas is resized.
- // Right now offscreen_gl_context generates a new FBO and the bound texture is changed
+ // Right now surfman generates a new FBO and the bound texture is changed
// in order to create a new render to texture attachment.
// Send a command to re-bind the TEXTURE_2D, if any.
if let Some(texture) = self
@@ -308,7 +305,7 @@ impl WebGLRenderingContext {
}
// Bound framebuffer must not change when the canvas is resized.
- // Right now offscreen_gl_context generates a new FBO on resize.
+ // Right now surfman generates a new FBO on resize.
// Send a command to re-bind the framebuffer, if any.
if let Some(fbo) = self.bound_framebuffer.get() {
let id = WebGLFramebufferBindingRequest::Explicit(fbo.id());
@@ -324,6 +321,10 @@ impl WebGLRenderingContext {
self.webgl_sender.context_id()
}
+ pub fn onscreen(&self) -> bool {
+ self.canvas.upcast::<Node>().is_connected()
+ }
+
#[inline]
pub fn send_command(&self, command: WebGLCommand) {
self.webgl_sender
@@ -337,6 +338,10 @@ impl WebGLRenderingContext {
.send(command, capture_webgl_backtrace(self));
}
+ pub fn swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) {
+ let _ = self.webgl_sender.send_swap_buffers(id);
+ }
+
#[inline]
pub fn send_vr_command(&self, command: WebVRCommand) {
self.webgl_sender.send_vr(command).unwrap();
@@ -438,13 +443,12 @@ impl WebGLRenderingContext {
}
let target = TexImageTarget::Texture2D;
- let info = texture.image_info_for_target(&target, 0);
- if info.is_initialized() {
+ if let Some(info) = texture.image_info_for_target(&target, 0) {
self.validate_filterable_texture(
&texture,
target,
0,
- info.internal_format().unwrap_or(TexFormat::RGBA),
+ info.internal_format(),
Size2D::new(info.width(), info.height()),
info.data_type().unwrap_or(TexDataType::UnsignedByte),
);
@@ -462,7 +466,7 @@ impl WebGLRenderingContext {
.dirty(NodeDamage::OtherNodeDamage);
let document = document_from_node(&*self.canvas);
- document.add_dirty_canvas(self.context_id());
+ document.add_dirty_canvas(self);
}
fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) {
@@ -746,7 +750,10 @@ impl WebGLRenderingContext {
pixels: TexPixels,
) {
// We have already validated level
- let image_info = texture.image_info_for_target(&target, level);
+ let image_info = match texture.image_info_for_target(&target, level) {
+ Some(info) => info,
+ None => return self.webgl_error(InvalidOperation),
+ };
// GL_INVALID_VALUE is generated if:
// - xoffset or yoffset is less than 0
@@ -761,9 +768,7 @@ impl WebGLRenderingContext {
}
// NB: format and internal_format must match.
- if format != image_info.internal_format().unwrap() ||
- data_type != image_info.data_type().unwrap()
- {
+ if format != image_info.internal_format() || data_type != image_info.data_type().unwrap() {
return self.webgl_error(InvalidOperation);
}
@@ -810,8 +815,9 @@ impl WebGLRenderingContext {
receiver.recv().unwrap()
}
- pub fn layout_handle(&self) -> webrender_api::ImageKey {
- self.webrender_image
+ pub(crate) fn layout_handle(&self) -> HTMLCanvasDataSource {
+ let image_key = self.webrender_image;
+ HTMLCanvasDataSource::WebGL(image_key)
}
// https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
@@ -1086,17 +1092,9 @@ impl WebGLRenderingContext {
self.bound_framebuffer.get()
}
- pub fn bound_renderbuffer(&self) -> Option<DomRoot<WebGLRenderbuffer>> {
- self.bound_renderbuffer.get()
- }
-
pub fn extension_manager(&self) -> &WebGLExtensions {
&self.extension_manager
}
-
- pub fn formats(&self) -> &GLFormats {
- &self.framebuffer_format
- }
}
#[cfg(not(feature = "webgl_backtrace"))]
@@ -1921,9 +1919,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Some(WebGLFramebufferAttachmentRoot::Renderbuffer(rb)) => {
TexFormat::from_gl_constant(rb.internal_format())
},
- Some(WebGLFramebufferAttachmentRoot::Texture(texture)) => {
- texture.image_info_for_target(&target, 0).internal_format()
- },
+ Some(WebGLFramebufferAttachmentRoot::Texture(texture)) => texture
+ .image_info_for_target(&target, 0)
+ .map(|info| info.internal_format()),
None => None,
},
None => {
@@ -2022,7 +2020,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
Err(_) => return,
};
- let image_info = texture.image_info_for_target(&target, level);
+ let image_info = match texture.image_info_for_target(&target, level) {
+ Some(info) => info,
+ None => return self.webgl_error(InvalidOperation),
+ };
// GL_INVALID_VALUE is generated if:
// - xoffset or yoffset is less than 0
@@ -2225,6 +2226,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
fn DeleteFramebuffer(&self, framebuffer: Option<&WebGLFramebuffer>) {
if let Some(framebuffer) = framebuffer {
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ // Can opaque framebuffers be deleted?
+ // https://github.com/immersive-web/webxr/issues/855
+ handle_potential_webgl_error!(self, framebuffer.validate_transparent(), return);
handle_potential_webgl_error!(self, self.validate_ownership(framebuffer), return);
handle_object_deletion!(
self,
@@ -2384,7 +2389,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
pname: u32,
) -> JSVal {
// Check if currently bound framebuffer is non-zero as per spec.
- if self.bound_framebuffer.get().is_none() {
+ if let Some(fb) = self.bound_framebuffer.get() {
+ // Opaque framebuffers cannot have their attachments inspected
+ // https://immersive-web.github.io/webxr/#opaque-framebuffer
+ handle_potential_webgl_error!(self, fb.validate_transparent(), return NullValue());
+ } else {
self.webgl_error(InvalidOperation);
return NullValue();
}
@@ -2487,6 +2496,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7
fn GetRenderbufferParameter(&self, _cx: SafeJSContext, target: u32, pname: u32) -> JSVal {
+ // We do not check to see if the renderbuffer came from an opaque framebuffer
+ // https://github.com/immersive-web/webxr/issues/862
let target_matches = target == constants::RENDERBUFFER;
let pname_matches = match pname {
@@ -3477,6 +3488,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if program.is_deleted() ||
!program.is_linked() ||
+ self.context_id() != location.context_id() ||
program.id() != location.program_id() ||
program.link_generation() != location.link_generation()
{
@@ -4153,7 +4165,7 @@ pub trait LayoutCanvasWebGLRenderingContextHelpers {
impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGLRenderingContext> {
#[allow(unsafe_code)]
unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource {
- HTMLCanvasDataSource::WebGL((*self.unsafe_get()).layout_handle())
+ (*self.unsafe_get()).layout_handle()
}
}
@@ -4347,7 +4359,7 @@ impl TexPixels {
}
#[derive(JSTraceable)]
-pub(crate) struct WebGLCommandSender {
+pub struct WebGLCommandSender {
sender: WebGLChan,
waker: Option<Box<dyn EventLoopWaker>>,
}
@@ -4410,6 +4422,18 @@ impl WebGLMessageSender {
self.wake_after_send(|| self.sender.send_vr(command))
}
+ pub fn send_swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) -> WebGLSendResult {
+ self.wake_after_send(|| self.sender.send_swap_buffers(id))
+ }
+
+ pub fn send_create_webxr_swap_chain(
+ &self,
+ size: Size2D<i32>,
+ sender: WebGLSender<Option<WebXRSwapChainId>>,
+ ) -> WebGLSendResult {
+ self.wake_after_send(|| self.sender.send_create_webxr_swap_chain(size, sender))
+ }
+
pub fn send_resize(
&self,
size: Size2D<u32>,
diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs
index e4a18b519a3..f7d52c8708a 100644
--- a/components/script/dom/webgltexture.rs
+++ b/components/script/dom/webgltexture.rs
@@ -40,7 +40,7 @@ pub struct WebGLTexture {
is_deleted: Cell<bool>,
/// Stores information about mipmap levels and cubemap faces.
#[ignore_malloc_size_of = "Arrays are cumbersome"]
- image_info_array: DomRefCell<[ImageInfo; MAX_LEVEL_COUNT * MAX_FACE_COUNT]>,
+ image_info_array: DomRefCell<[Option<ImageInfo>; MAX_LEVEL_COUNT * MAX_FACE_COUNT]>,
/// Face count can only be 1 or 6
face_count: Cell<u8>,
base_mipmap_level: u32,
@@ -64,7 +64,7 @@ impl WebGLTexture {
base_mipmap_level: 0,
min_filter: Cell::new(constants::NEAREST_MIPMAP_LINEAR),
mag_filter: Cell::new(constants::LINEAR),
- image_info_array: DomRefCell::new([ImageInfo::new(); MAX_LEVEL_COUNT * MAX_FACE_COUNT]),
+ image_info_array: DomRefCell::new([None; MAX_LEVEL_COUNT * MAX_FACE_COUNT]),
attached_to_dom: Cell::new(false),
attached_framebuffer: Default::default(),
}
@@ -135,8 +135,7 @@ impl WebGLTexture {
width: width,
height: height,
depth: depth,
- internal_format: Some(internal_format),
- is_initialized: true,
+ internal_format: internal_format,
data_type: data_type,
};
@@ -159,10 +158,7 @@ impl WebGLTexture {
},
};
- let base_image_info = self.base_image_info();
- if !base_image_info.is_initialized() {
- return Err(WebGLError::InvalidOperation);
- }
+ let base_image_info = self.base_image_info().ok_or(WebGLError::InvalidOperation)?;
let is_cubic = target == constants::TEXTURE_CUBE_MAP;
if is_cubic && !self.is_cube_complete() {
@@ -210,7 +206,7 @@ impl WebGLTexture {
let currently_bound_framebuffer =
self.upcast::<WebGLObject>().context().bound_framebuffer();
if let Some(fb) = currently_bound_framebuffer {
- fb.detach_texture(self);
+ let _ = fb.detach_texture(self);
}
let cmd = WebGLCommand::DeleteTexture(self.id);
@@ -308,10 +304,9 @@ impl WebGLTexture {
}
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() {
- return Err(WebGLError::InvalidOperation);
- }
+ let base_image_info = self
+ .image_info_at_face(0, first_level)
+ .ok_or(WebGLError::InvalidOperation)?;
let mut ref_width = base_image_info.width;
let mut ref_height = base_image_info.height;
@@ -333,7 +328,6 @@ impl WebGLTexture {
height: ref_height,
depth: 0,
internal_format: base_image_info.internal_format,
- is_initialized: base_image_info.is_initialized(),
data_type: base_image_info.data_type,
};
@@ -345,19 +339,19 @@ impl WebGLTexture {
fn is_cube_complete(&self) -> bool {
debug_assert_eq!(self.face_count.get(), 6);
- let image_info = self.base_image_info();
- if !image_info.is_defined() {
- return false;
- }
+ let image_info = match self.base_image_info() {
+ Some(info) => info,
+ None => return false,
+ };
let ref_width = image_info.width;
let ref_format = image_info.internal_format;
for face in 0..self.face_count.get() {
- let current_image_info = self.image_info_at_face(face, self.base_mipmap_level);
- if !current_image_info.is_defined() {
- return false;
- }
+ let current_image_info = match self.image_info_at_face(face, self.base_mipmap_level) {
+ Some(info) => info,
+ None => return false,
+ };
// Compares height with width to enforce square dimensions
if current_image_info.internal_format != ref_format ||
@@ -383,12 +377,12 @@ impl WebGLTexture {
}
}
- pub fn image_info_for_target(&self, target: &TexImageTarget, level: u32) -> ImageInfo {
+ pub fn image_info_for_target(&self, target: &TexImageTarget, level: u32) -> Option<ImageInfo> {
let face_index = self.face_index_for_target(&target);
self.image_info_at_face(face_index, level)
}
- pub fn image_info_at_face(&self, face: u8, level: u32) -> ImageInfo {
+ pub fn image_info_at_face(&self, face: u8, level: u32) -> Option<ImageInfo> {
let pos = (level * self.face_count.get() as u32) + face as u32;
self.image_info_array.borrow()[pos as usize]
}
@@ -402,10 +396,10 @@ impl WebGLTexture {
fn set_image_infos_at_level_and_face(&self, level: u32, face: u8, image_info: ImageInfo) {
debug_assert!(face < self.face_count.get());
let pos = (level * self.face_count.get() as u32) + face as u32;
- self.image_info_array.borrow_mut()[pos as usize] = image_info;
+ self.image_info_array.borrow_mut()[pos as usize] = Some(image_info);
}
- fn base_image_info(&self) -> ImageInfo {
+ fn base_image_info(&self) -> Option<ImageInfo> {
assert!((self.base_mipmap_level as usize) < MAX_LEVEL_COUNT);
self.image_info_at_face(0, self.base_mipmap_level)
@@ -435,23 +429,11 @@ pub struct ImageInfo {
width: u32,
height: u32,
depth: u32,
- internal_format: Option<TexFormat>,
- is_initialized: bool,
+ internal_format: TexFormat,
data_type: Option<TexDataType>,
}
impl ImageInfo {
- fn new() -> ImageInfo {
- ImageInfo {
- width: 0,
- height: 0,
- depth: 0,
- internal_format: None,
- is_initialized: false,
- data_type: None,
- }
- }
-
pub fn width(&self) -> u32 {
self.width
}
@@ -460,7 +442,7 @@ impl ImageInfo {
self.height
}
- pub fn internal_format(&self) -> Option<TexFormat> {
+ pub fn internal_format(&self) -> TexFormat {
self.internal_format
}
@@ -474,14 +456,6 @@ impl ImageInfo {
self.depth.is_power_of_two()
}
- pub fn is_initialized(&self) -> bool {
- self.is_initialized
- }
-
- fn is_defined(&self) -> bool {
- self.internal_format.is_some()
- }
-
fn get_max_mimap_levels(&self) -> u32 {
let largest = cmp::max(cmp::max(self.width, self.height), self.depth);
if largest == 0 {
@@ -492,10 +466,7 @@ impl ImageInfo {
}
fn is_compressed_format(&self) -> bool {
- match self.internal_format {
- Some(format) => format.is_compressed(),
- None => false,
- }
+ self.internal_format.is_compressed()
}
}
diff --git a/components/script/dom/webgluniformlocation.rs b/components/script/dom/webgluniformlocation.rs
index bf142480dc7..5bdc661f17a 100644
--- a/components/script/dom/webgluniformlocation.rs
+++ b/components/script/dom/webgluniformlocation.rs
@@ -7,6 +7,7 @@ use crate::dom::bindings::codegen::Bindings::WebGLUniformLocationBinding;
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
use crate::dom::bindings::root::DomRoot;
use crate::dom::window::Window;
+use canvas_traits::webgl::WebGLContextId;
use canvas_traits::webgl::WebGLProgramId;
use dom_struct::dom_struct;
@@ -14,6 +15,7 @@ use dom_struct::dom_struct;
pub struct WebGLUniformLocation {
reflector_: Reflector,
id: i32,
+ context_id: WebGLContextId,
program_id: WebGLProgramId,
link_generation: u64,
size: Option<i32>,
@@ -23,6 +25,7 @@ pub struct WebGLUniformLocation {
impl WebGLUniformLocation {
fn new_inherited(
id: i32,
+ context_id: WebGLContextId,
program_id: WebGLProgramId,
link_generation: u64,
size: Option<i32>,
@@ -31,6 +34,7 @@ impl WebGLUniformLocation {
Self {
reflector_: Reflector::new(),
id,
+ context_id,
program_id,
link_generation,
size,
@@ -41,6 +45,7 @@ impl WebGLUniformLocation {
pub fn new(
window: &Window,
id: i32,
+ context_id: WebGLContextId,
program_id: WebGLProgramId,
link_generation: u64,
size: Option<i32>,
@@ -49,6 +54,7 @@ impl WebGLUniformLocation {
reflect_dom_object(
Box::new(Self::new_inherited(
id,
+ context_id,
program_id,
link_generation,
size,
@@ -67,6 +73,10 @@ impl WebGLUniformLocation {
self.program_id
}
+ pub fn context_id(&self) -> WebGLContextId {
+ self.context_id
+ }
+
pub fn link_generation(&self) -> u64 {
self.link_generation
}
diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs
index 41f8392acfb..6fbdc592b0e 100644
--- a/components/script/dom/xrsession.rs
+++ b/components/script/dom/xrsession.rs
@@ -6,7 +6,6 @@ use crate::compartments::InCompartment;
use crate::dom::bindings::callback::ExceptionHandling;
use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorBinding::NavigatorMethods;
-use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenceSpaceType;
@@ -30,7 +29,6 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::node::Node;
use crate::dom::node::NodeDamage;
use crate::dom::promise::Promise;
-use crate::dom::webglframebuffer::WebGLFramebufferAttachmentRoot;
use crate::dom::xrframe::XRFrame;
use crate::dom::xrinputsourcearray::XRInputSourceArray;
use crate::dom::xrinputsourceevent::XRInputSourceEvent;
@@ -41,7 +39,6 @@ use crate::dom::xrspace::XRSpace;
use crate::dom::xrwebgllayer::XRWebGLLayer;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
-use euclid::default::Size2D;
use euclid::RigidTransform3D;
use ipc_channel::ipc::IpcSender;
use ipc_channel::router::ROUTER;
@@ -77,6 +74,9 @@ pub struct XRSession {
end_promises: DomRefCell<Vec<Rc<Promise>>>,
/// https://immersive-web.github.io/webxr/#ended
ended: Cell<bool>,
+ /// Opaque framebuffers need to know the session is "outside of a requestAnimationFrame"
+ /// https://immersive-web.github.io/webxr/#opaque-framebuffer
+ outside_raf: Cell<bool>,
}
impl XRSession {
@@ -102,6 +102,7 @@ impl XRSession {
input_sources: Dom::from_ref(input_sources),
end_promises: DomRefCell::new(vec![]),
ended: Cell::new(false),
+ outside_raf: Cell::new(true),
}
}
@@ -169,6 +170,10 @@ impl XRSession {
self.session.borrow_mut().request_animation_frame(sender);
}
+ pub fn is_outside_raf(&self) -> bool {
+ self.outside_raf.get()
+ }
+
fn attach_event_handler(&self) {
let this = Trusted::new(self);
let global = self.global();
@@ -276,6 +281,8 @@ impl XRSession {
/// https://immersive-web.github.io/webxr/#xr-animation-frame
fn raf_callback(&self, (time, mut frame): (f64, Frame)) {
+ debug!("WebXR RAF callback");
+
// Step 1
if let Some(pending) = self.pending_render_state.take() {
// https://immersive-web.github.io/webxr/#apply-the-pending-render-state
@@ -285,19 +292,8 @@ impl XRSession {
// Step 6-7: XXXManishearth handle inlineVerticalFieldOfView
// XXXManishearth handle inline sessions and composition disabled flag
- if let Some(layer) = pending.GetBaseLayer() {
- let attachment = layer.framebuffer().attachment(constants::COLOR_ATTACHMENT0);
- if let Some(WebGLFramebufferAttachmentRoot::Texture(texture)) = attachment {
- let context = layer.Context().context_id().0;
- let texture_id = texture.id().get();
- if let Some((width, height)) = layer.framebuffer().size() {
- let size = Size2D::new(width, height);
- self.session
- .borrow_mut()
- .set_texture(context, texture_id, size);
- }
- }
- }
+ let swap_chain_id = pending.GetBaseLayer().map(|layer| layer.swap_chain_id());
+ self.session.borrow_mut().set_swap_chain(swap_chain_id);
}
for event in frame.events.drain(..) {
@@ -321,13 +317,16 @@ impl XRSession {
frame.set_animation_frame(true);
// Step 8
+ self.outside_raf.set(false);
for (_, callback) in callbacks.drain(..) {
if let Some(callback) = callback {
let _ = callback.Call__(Finite::wrap(time), &frame, ExceptionHandling::Report);
}
}
+ self.outside_raf.set(true);
frame.set_active(false);
+ base_layer.swap_buffers();
self.session.borrow_mut().render_animation_frame();
self.request_new_xr_frame();
diff --git a/components/script/dom/xrwebgllayer.rs b/components/script/dom/xrwebgllayer.rs
index f637f4ee96e..44bc10868b6 100644
--- a/components/script/dom/xrwebgllayer.rs
+++ b/components/script/dom/xrwebgllayer.rs
@@ -2,27 +2,26 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods};
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit;
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
-use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
-use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
use crate::dom::bindings::error::Error;
use crate::dom::bindings::error::Fallible;
-use crate::dom::bindings::reflector::{reflect_dom_object, Reflector, DomObject};
+use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::globalscope::GlobalScope;
-use crate::dom::webgl_validations::types::TexImageTarget;
use crate::dom::webglframebuffer::WebGLFramebuffer;
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
use crate::dom::window::Window;
use crate::dom::xrsession::XRSession;
use crate::dom::xrview::XRView;
use crate::dom::xrviewport::XRViewport;
+use canvas_traits::webgl::WebGLFramebufferId;
use dom_struct::dom_struct;
-use js::rust::CustomAutoRooter;
use std::convert::TryInto;
+use webxr_api::SwapChainId as WebXRSwapChainId;
use webxr_api::Views;
#[dom_struct]
@@ -32,6 +31,8 @@ pub struct XRWebGLLayer {
depth: bool,
stencil: bool,
alpha: bool,
+ #[ignore_malloc_size_of = "ids don't malloc"]
+ swap_chain_id: WebXRSwapChainId,
context: Dom<WebGLRenderingContext>,
session: Dom<XRSession>,
framebuffer: Dom<WebGLFramebuffer>,
@@ -39,6 +40,7 @@ pub struct XRWebGLLayer {
impl XRWebGLLayer {
pub fn new_inherited(
+ swap_chain_id: WebXRSwapChainId,
session: &XRSession,
context: &WebGLRenderingContext,
init: &XRWebGLLayerInit,
@@ -50,6 +52,7 @@ impl XRWebGLLayer {
depth: init.depth,
stencil: init.stencil,
alpha: init.alpha,
+ swap_chain_id,
context: Dom::from_ref(context),
session: Dom::from_ref(session),
framebuffer: Dom::from_ref(framebuffer),
@@ -58,6 +61,7 @@ impl XRWebGLLayer {
pub fn new(
global: &GlobalScope,
+ swap_chain_id: WebXRSwapChainId,
session: &XRSession,
context: &WebGLRenderingContext,
init: &XRWebGLLayerInit,
@@ -65,6 +69,7 @@ impl XRWebGLLayer {
) -> DomRoot<XRWebGLLayer> {
reflect_dom_object(
Box::new(XRWebGLLayer::new_inherited(
+ swap_chain_id,
session,
context,
init,
@@ -89,108 +94,16 @@ impl XRWebGLLayer {
// XXXManishearth step 3: throw error if context is lost
// XXXManishearth step 4: check XR compat flag for immersive sessions
- let cx = global.get_cx();
- let old_fbo = context.bound_framebuffer();
- let old_rbo = context.bound_renderbuffer();
- let old_texture = context
- .textures()
- .active_texture_for_image_target(TexImageTarget::Texture2D);
-
- // Step 9.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with
- // context and layerInit’s depth, stencil, and alpha values."
- let framebuffer = context.CreateFramebuffer().ok_or(Error::Operation)?;
+ // Step 9.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with context."
+ let size = session.with_session(|session| session.recommended_framebuffer_resolution());
+ let (swap_chain_id, framebuffer) =
+ WebGLFramebuffer::maybe_new_webxr(session, context, size).ok_or(Error::Operation)?;
// Step 9.3. "Allocate and initialize resources compatible with session’s XR device,
// including GPU accessible memory buffers, as required to support the compositing of layer."
- // Create a new texture with size given by the session's recommended resolution
- let texture = context.CreateTexture().ok_or(Error::Operation)?;
- let render_buffer = context.CreateRenderbuffer().ok_or(Error::Operation)?;
- let resolution = session.with_session(|s| s.recommended_framebuffer_resolution());
- let mut pixels = CustomAutoRooter::new(None);
- let mut clear_bits = constants::COLOR_BUFFER_BIT;
-
- let formats = context.formats();
-
- context.BindTexture(constants::TEXTURE_2D, Some(&texture));
- let sc = context.TexImage2D(
- constants::TEXTURE_2D,
- 0,
- formats.texture_format,
- resolution.width,
- resolution.height,
- 0,
- formats.texture_format,
- formats.texture_type,
- pixels.root(*cx),
- );
-
- // Bind the new texture to the framebuffer
- context.BindFramebuffer(constants::FRAMEBUFFER, Some(&framebuffer));
- context.FramebufferTexture2D(
- constants::FRAMEBUFFER,
- constants::COLOR_ATTACHMENT0,
- constants::TEXTURE_2D,
- Some(&texture),
- 0,
- );
-
- // Create backing store and bind a renderbuffer if requested
- if init.depth || init.stencil {
- let (internal_format, attachment) = if init.depth && init.stencil {
- clear_bits |= constants::DEPTH_BUFFER_BIT | constants::STENCIL_BUFFER_BIT;
- (
- constants::DEPTH_STENCIL,
- constants::DEPTH_STENCIL_ATTACHMENT,
- )
- } else if init.depth {
- clear_bits |= constants::DEPTH_BUFFER_BIT;
- (constants::DEPTH_COMPONENT16, constants::DEPTH_ATTACHMENT)
- } else {
- clear_bits |= constants::STENCIL_BUFFER_BIT;
- (constants::STENCIL_INDEX8, constants::STENCIL_ATTACHMENT)
- };
- context.BindRenderbuffer(constants::RENDERBUFFER, Some(&render_buffer));
- context.RenderbufferStorage(
- constants::RENDERBUFFER,
- internal_format,
- resolution.width,
- resolution.height,
- );
- context.FramebufferRenderbuffer(
- constants::FRAMEBUFFER,
- attachment,
- constants::RENDERBUFFER,
- Some(&render_buffer),
- );
- }
-
- context.initialize_framebuffer(clear_bits);
-
- // Restore the WebGL state while complaining about global mutable state
- let fb_status = context.CheckFramebufferStatus(constants::FRAMEBUFFER);
- let gl_status = context.GetError();
- context.BindTexture(constants::TEXTURE_2D, old_texture.as_ref().map(|t| &**t));
- context.BindFramebuffer(constants::FRAMEBUFFER, old_fbo.as_ref().map(|f| &**f));
- context.BindRenderbuffer(constants::RENDERBUFFER, old_rbo.as_ref().map(|f| &**f));
-
// Step 9.4: "If layer’s resources were unable to be created for any reason,
// throw an OperationError and abort these steps."
- if let Err(err) = sc {
- error!("TexImage2D error {:?} while creating XR context", err);
- return Err(Error::Operation);
- }
- if fb_status != constants::FRAMEBUFFER_COMPLETE {
- error!(
- "Framebuffer error {:x} while creating XR context",
- fb_status
- );
- return Err(Error::Operation);
- }
- if gl_status != constants::NO_ERROR {
- error!("GL error {:x} while creating XR context", gl_status);
- return Err(Error::Operation);
- }
// Ensure that we finish setting up this layer before continuing.
context.Finish();
@@ -198,6 +111,7 @@ impl XRWebGLLayer {
// Step 10. "Return layer."
Ok(XRWebGLLayer::new(
&global.global(),
+ swap_chain_id,
session,
context,
init,
@@ -205,12 +119,18 @@ impl XRWebGLLayer {
))
}
+ pub fn swap_chain_id(&self) -> WebXRSwapChainId {
+ self.swap_chain_id
+ }
+
pub fn session(&self) -> &XRSession {
&self.session
}
- pub fn framebuffer(&self) -> &WebGLFramebuffer {
- &self.framebuffer
+ pub fn swap_buffers(&self) {
+ if let WebGLFramebufferId::Opaque(id) = self.framebuffer.id() {
+ self.context.swap_buffers(Some(id));
+ }
}
}